De sysctl-variabele vfs.vmiodirenable
kan de waarde 0 (uit) of 1 (aan) hebben. De standaardwaarde
is 1. Deze variabele bepaalt hoe mappen door het systeem in
een cache bewaard worden. De meeste mappen zijn klein en
gebruiken slechts een klein fragment (typisch 1 K) in het
bestandssysteem en nog minder (typisch 512 bytes) in de
buffercache. Als deze variabele uit staat (op 0) bewaart de
buffercache slechts een bepaald aantal mappen in de cache, ook
al is er een overvloed aan geheugen beschikbaar. Wanneer deze
aan staat (op 1), wordt de VM paginacache gebruikt, waardoor
voor het cachen van mappen al het geheugen kan worden
gebruikt. Het is echter wel zo dat het minimale in-core
geheugen dat gebruikt wordt om een map te cachen in dat geval
de fysieke paginagrootte is (typisch 4 K) in plaats van
512 bytes. Het is aan te raden deze optie aan te laten
staan als gebruik gemaakt wordt van diensten die met grote
aantallen bestanden werken, zoals webcaches, grote
mailsystemen en newsservers. Als deze optie aan blijft staan,
verlaagt die de prestaties niet, ook al kost het meer
geheugen. Door experimenteren is dit voor een systeem na te
gaan.
De sysctl-variabele vfs.write_behind
staat standaard aan (1
). Dit betekent dat
het bestandssysteem gegevens naar het medium gaat schrijven op
het moment dat er een volledig cluster aan gegevens verzameld
is. Dit is meestal het geval bij het schrijven van grote
sequentiële bestanden. Het idee is om te voorkomen dat
de buffercache verzadigd raakt met vuile buffers zonder dat
dit bijdraagt aan de I/O-prestaties. Dit kan echter processen
ophouden en onder sommige omstandigheden is het wellicht beter
deze sysctl uit te zetten.
De sysctl-variabele vfs.hirunningspace
bepaalt hoeveel nog te schrijven gegevens er in het complete
systeem op elk moment in de wachtrij naar schijfcontrollers
mag staan. De standaardwaarde is meestal voldoende, maar op
machines met veel schijven, is het beter deze te verhogen naar
vier of vijf megabyte. Het instellen van
een te hoge waarde (groter dan de schrijfdrempel van de
buffercache) kan leiden tot zeer slechte prestaties bij
clustering. Stel deze waarde niet arbitrair hoog in! Hogere
schrijfwaarden kunnen vertraging veroorzaken in het lezen, als
dit tegelijk plaatsvindt.
Er zijn verscheidene andere sysctl's voor buffercache en VM-pagecache. Het wordt afgeraden deze te wijzigen. Het VM-systeem is zeer goed in staat zichzelf automatisch te optimaliseren.
De sysctl-variabele
vm.swap_idle_enabled
is nuttig in grote
meergebruikersystemen met veel gebruikers die af- en aanmelden
en veel onbenutte processen. Dergelijke systemen hebben de
neiging om voortdurend de vrije geheugenreserves onder druk
te zetten. Het is mogelijk om de prioriteit van
geheugenpagina's die verband houden met onbenutte processen
sneller te laten dalen dan met het normale pageout-algoritme,
door deze sysctl aan te zetten en via
vm.swap_idle_threshold1
en
vm.swap_idle_threshold2
de swapout
hysterese (in seconden onbenut) af te stemmen. Deze optie
dient alleen gebruikt te worden als ze echt nodig is, want de
andere kant van de medaille is dat dit eerder pre-page
geheugen inhoudt in plaats van later, waardoor het meer
wisselbestand- en schijfbandbreedte kost. In een klein
systeem heeft deze optie een voorspelbaar effect, maar in
grote systemen waar al sprake is van een matige paging kan
deze optie het mogelijk maken voor het VM-systeem om hele
processen gemakkelijk in en uit het geheugen te halen.
Ten tijde van FreeBSD 4.3 is er geflirt met het
uitzetten van IDE-schrijfcaching. Hierdoor neemt de
bandbraadte naar IDE-schijven af, maar het werd als
noodzakelijk beschouwd vanwege ernstige problemen met
gegevensinconsistentie die door harde schijfproducenten
geëintroduceerd waren. Het probleem is dat IDE-schijven
niet de waarheid vertellen over wanneer een schrijfactie
klaar is. Door IDE-schrijfcaching wordt data niet alleen
ongeordend geschreven, maar soms kan zelfs het schrijven van
sommige blokken voortdurend uitgesteld worden als er sprake is
van een hoge schijfbelasting. Een crash of stroomstoring kan
dan ernstige corruptie aan het bestandssysteem veroorzaken.
Daarom werd de standaardinstelling van FreeBSD voor alle
zekerheid gewijzigd. Helaas was het resultaat een groot
verlies aan prestaties en na die uitgave is de
standaardwaarde weer terug veranderd. Met de sysctl-variabele
hw.ata.wc
kan gecontroleerd worden of
schrijfcaching aan of uit staat. Als schrijfcaching uit
staat, kan het die weer aangezet worden door
hw.ata.wc
op 1 te zetten. Aangezien dit
een kernelvariabele is, moet deze ingesteld worden vanuit de
bootloader tijdens het opstarten. Nadat de kernel eenmaal
opgestart is, heeft het wijzigen van deze sysctl geen
effect.
Meer informatie staat in ata(4).
De kernelinstelling SCSI_DELAY
kan
gebruikt worden om de opstarttijd te versnellen. De
standaardwaarde is nogal hoog en kan 15
seconden vertraging veroorzaken. Met modernere SCSI-systemen
is 5
seconden al voldoende (zeker met
moderne schijven). De kern.cam.scsi_delay
opstart variabele moet hier gebruikt worden. De variabele
en kernelconfiguratie-optie accepteren waarden uitgedrukt
in milliseconden en
niet in
seconden.
tunefs(8) kan gebruikt worden om een bestandsysteem nauwkeurig af te stellen. Het heeft veel opties, maar nu wordt alleen het aan- en uitzetten van softupdates besproken. Dat gaat als volgt:
#
tunefs -n enable /filesystem
#
tunefs -n disable /filesystem
Een bestandssysteem kan niet met tunefs(8) gewijzigd worden als het aangekoppeld is. Softupdates aanzetten wordt dus in het algemeen gedaan vanuit enkelegebruikermodus, voordat partities aangekoppeld zijn.
Softupdates zorgen voor een drastische verbetering van de
prestaties met betrekking tot metagegevens, met name het
aanmaken en verwijderen van bestanden, door gebruik van een
geheugencache. Het wordt dan ook aangeraden om op alle
bestandssystemen softupdates te gebruiken. Er zijn twee nadelen
aan softupdates: softupdates garanderen een consistent
bestandssysteem in geval van een crash, maar het kan makkelijk
enkele seconden (zelfs een minuut) achter liggen met het
daadwerkelijk bijwerken op de fysieke harde schijf. Als een
systeem crasht gaat wellicht meer werk verloren dan anders het
geval zou zijn. Daarnaast vertragen softupdates het vrijgeven
van bestandssysteemblokken. Als een bestandssysteem (zoals de
rootpartitie) bijna vol is, dan kan het verrichten van een grote
update, zoals make installworld
, ertoe leiden
dat het bestandssysteem ruimtegebrek krijgt en dat daardoor de
operatie mislukt.
Er zijn traditioneel twee methodes om de metagegevens van een bestandssysteem terug naar de schijf te schrijven. Het bijwerken van metagegevens houdt het bijwerken van van niet-inhoudelijke gegevens zoals inodes of mappen in.
Historisch gezien was het gebruikelijk om updates aan
metagegevens synchroon weg te schrijven. Als een map
bijvoorbeeld gewijzigd was, wachtte het systeem totdat de
verandering daadwerkelijk naar de schijf geschreven was. De
gegevensbuffers (de inhoud van een bestand) werden
doorgeschoven naar de buffercache en op een later moment
asynchroon op de schijf opgeslagen. Het voordeel van deze
benadering is dat ze altijd veilig is. Als het systeem faalt
tijdens het bijwerken, zijn de metagegevens nog altijd
consistent. Een bestand kan volledig gecreëerd zijn of
helemaal niet. Als de gegevensblokken van een bestand nog
niet van de buffercache naar de schijf geschreven zijn ten
tijde van de crash, is fsck(8) in staat om dit te
herkennen en het bestandssysteem te repareren door de lengte
van het bestand nul te maken. Deze implementatie is ook
helder en eenvoudig. Het nadeel is echter dat het wijzigen
van metagegevens een traag proces is. Een
rm -r
benadert bijvoorbeeld alle bestanden
in een map sequentiëel, maar elke mapverandering
(verwijderen van een bestand) wordt synchroon naar de schijf
geschreven. Dit omvat ook het bijwerken van de map zelf, van
de inodetabel en mogelijk ook van indirecte blokken die voor
het bestand in kwestie zijn gealloceerd. Gelijksoortige
processen spelen zich af bij een commando als
tar -x
, waarbij een grote
bestandshiëearchie wordt uitgepakt.
De tweede mogelijkheid is om het bijwerken van
metagegevens asynchroon weg te schrijven. Dit is standaard in
Linux®/ext2fs en als een *BSD UFS-bestandssysteem met
mount -o async
aangekoppeld is, is de
werking hetzelfde. Alle bijwerkingen aan metagegevens worden
eenvoudigweg doorgegeven aan de buffercache en vermengd met
inhoudelijke updates van de bestandsgegevens. Het voordeel
is een grote winst aan snelheid, omdat er niet telkens gewacht
hoeft te worden op het bijwerken van metagegevens tot deze
daadwerkelijk naar de schijf geschreven zijn. De
implementatie is ook in dit geval helder en eenvoudig. Het
grote nadeel is uiteraard dat er geen enkele garantie is voor
de consistentie van het bestandssysteem. Als het systeem
faalt tijdens een operatie waarbij veel metagegevens worden
bijgewerkt (bijvoorbeeld door een stroomstoring of iemand
drukt op de resetknop), blijft het bestandssysteem in een
onvoorspelbare toestand achter. Er is geen mogelijkheid om de
toestand van het bestandssysteem te onderzoeken als het
systeem weer opstart, want de gegevensblokken van een bestand
kunnen al weggeschreven zijn geweest terwijl het wegschrijven
van bijwerkingen aan de inodetabel of de bijhorende map nog
niet plaats heeft gevonden. Het is zelfs onmogelijk om een
fsck
te implementeren die de overgebleven
chaos kan opruimen: de benodigde informatie is gewoon niet
volledig aanwezig op de schijf. Als een bestandssysteem op
deze manier onherstelbaar beschadigd is, is de enige optie
newfs(8) te gebruiken en vervolgens te herstellen van
een back-up.
De gebruikelijke oplossing voor dit probleem is het implementeren van dirty region logging, ook wel journaling genoemd, hoewel deze term niet consistent gebruikt wordt en soms ook wordt gebruikt voor andere vormen van transactielogging. Het bijwerken van metagegevens wordt nog steeds synchroon geschreven, maar slechts naar een klein gebied van de schijf. Later worden ze dan naar de juiste locatie verplaatst. Omdat het loggebied klein is, hoeven de koppen van de schijf zelfs tijdens schrijfintensieve operaties nog maar over een kleine fysieke afstand te bewegen en door deze snellere respons zijn dit soort operaties sneller dan op de traditionele manier. De extra complexiteit van de implementatie is nogal beperkt, dus het risico van introductie van extra bugs valt mee. Een nadeel is dat alle metagegevens tweemaal geschreven worden (eerst naar het loggebied en later nog eens naar de definitieve locatie). Dus bij normaal gebruik kan er sprake zijn van wat men wel noemt een “performance pessimization”. Anderzijds kunnen in geval van een crash alle nog uitstaande metagegevensoperaties snel worden teruggedraaid of vanuit het loggebied alsnog worden afgemaakt wanneer de machine weer opstart. Het bestandssysteem start dan snel op.
Kirk McKusick, de vader van het Berkeley FFS, loste dit
probleem op met softupdates, wat betekent dat alle uitstaande
acties voor het bijwerken van metagegevens in het geheugen
bewaard worden en dan geordend naar de schijf geschreven
worden. Dit heeft het gevolg dat in geval van intensieve
operaties met betrekking tot metagegevens, latere bijwerkingen
aan een item eerdere bewerkingen opvangen
(“catch”) als deze nog in het geheugen zitten en
nog niet weggeschreven waren. Dus alle operaties, op
bijvoorbeeld een map, worden in het algemeen eerst in het
geheugen uitgevoerd voordat er wordt bijgewerkt naar schijf.
De gegevensblokken worden geordend conform hun positie, zodat
ze nooit weggeschreven worden voordat hun metagegevens
geschreven zijn. Als het systeem een crash ondervindt,
veroorzaakt dat impliciet het terugdraaien van uitstaande
operaties (“log rewind”): alle operaties die nog
niet weggeschreven waren lijken nooit gebeurd te zijn. Zo
wordt een consistent bestandssysteem in stand gehouden dat
eruit ziet alsof het 30 tot 60 seconden eerder was. Het
gebruikte algoritme garandeert dat alle bronnen die in gebruik
zijn als zodanig gemarkeerd worden in hun daarvoor geschikte
bitmaps: blokken en inodes. Na een crash is de enige
allocatiefout die kan optreden dat bronnen gemarkeerd kunnen
zijn als in gebruik (“used”), terwijl ze
feitelijk alweer beschikbaar (“free”) zijn.
fsck(8) herkent deze situatie en stelt dergelijke vrij
te maken bronnen opnieuw beschikbaar. Het is volkomen veilig
om na een crash te negeren dat het bestandssysteem niet schoon
is en het tot aankoppelen te dwingen met
mount -f
. Om niet langer gebruikte
bronnen vrij te maken moet later fsck(8) uitgevoerd
worden. Dit is dan ook het idee achter background
fsck: op het moment dat het systeem aan het
opstarten is, wordt er alleen een
snapshot van het systeem bewaard.
fsck
kan later uitgevoerd worden. Alle
bestandssystemen kunnen “dirty” aangekoppeld
worden en het systeem kan gewoon verder opstarten naar
meergebruikermodus. Vervolgens zijn er
fsck
s gepland die in de achtergrond draaien
voor elk bestandssysteem dat niet schoon is en waarmee
bezette bronnen vrijgegeven worden. Bestandssystemen die geen
gebruik maken van softupdates moeten echter nog steeds gebruik
maken van de normale fsck
in de
voorgrond.
Het voordeel van softupdates is dat operaties op
metagegevens bijna net zo snel zijn als asynchrone updates
(dat wil zeggen sneller dan met logging,
waarbij de metagegevens keer op keer geschreven worden).
Nadelen zijn de complexiteit van de code (wat een groter
risico op bugs impliceert in een gebied dat bijzonder
gevoelig is voor verlies van gebruikersgegevens) en een
groter geheugenverbruik. Tevens moet de gebruiker wennen aan
enkele eigenaardigheden. Na een crash lijkt de toestand van
het bestandssysteem wat “ouder”. In situaties
waar de standaard synchrone benadering een aantal lege
bestanden zou hebben achtergelaten na
fsck
, is het met softupdates juist zo dat
dergelijke bestanden er helemaal niet zijn, omdat de
metagegevens of de bestandsinhoud nooit naar de schijf zijn
geschreven. Schijfruimte wordt pas vrijgegeven als de
bijwerkingen aan metagegevens en inhoudelijke
bestandsgegevens weggeschreven zijn, wat mogelijk pas enige
tijd na het uitvoeren van rm
plaatsvindt.
Dit kan problemen veroorzaken als er grote hoeveelheden
gegevens naar een bestandssysteem geschreven worden dat
onvoldoende vrije ruimte heeft om alle bestanden twee keer te
kunnen bevatten (bijvoorbeeld in /tmp
).
All FreeBSD documents are available for download at http://ftp.FreeBSD.org/pub/FreeBSD/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.