Filecontainers zijn op zichzelf staande bestandssystemen — ook images genoemd — waarin bestanden en mappen kunnen worden opgeslagen. Ze werden vroeger gebruikt om schaduwkopieën van cd's en dvd's — ISO's — te maken, maar worden inmiddels vaker gebruikt om back-ups van partities of zelfs hele harddisks te maken. Op die manier kun je een grote hoeveelheid data, in één afgesloten bestand, gemakkelijk verplaatsen naar andere dragers — ongeacht welk bestandssysteem er op deze drager aanwezig is.

Deze filecontainers kunnen je vervolgens mounten waardoor de bestandsstructuur in de filecontainer zichtbaar wordt. Mount je de container als read-only dan kun je de data alleen lezen, maar mount je deze als read-write dan kun je er ook data naartoe wegschrijven. Van het laatste gaan we in dit voorbeeld uit.

Filecontainer maken

Om een nieuwe filecontainer te maken, creëer je een zero-filled bestand met onderstaande opdracht:

dd if=/dev/zero of=test.img bs=1M count=1000

Het bestand wordt nu 1000x1MB oftewel 1GB groot. Wanneer je de count-parameter aanpast kun je een groter bestand maken, echter kun je dat ook volgens onderstaande stappen met resize2fs doen zodra er een filesysteem op geïnitieerd is.

Eventueel kun je het commando opsplitsen en door pv laten lopen om de voortgang te zien. Onderstaand als voorbeeld een container van 200G met progressbar:

dd if=/dev/zero bs=1M count=200000 | pv -s 200G | dd of=test200gb.img

Het bestand dat je hiermee gemaakt hebt is nog leeg, er is nog geen bestandssysteem geïnitieerd waardoor er ook geen bestanden naartoe weggeschreven kunnen worden. Dit los je op via mkfs:

# EXT4 filesystem:
mkfs.ext4 -F -q test200gb.img
# EXT2 filesystem (though I strongly recomment ext4 since it's fourth gen):
mkfs.ext2 -F -q test200gb.img

Filecontainer in gebruik nemen (mounten)

Om naar de filecontainer te schrijven of van de container te kunnen lezen, dient deze gemount te worden. Hiervoor dient er allereerst een mounting-point gemaakt te worden — een map die uiteindelijk als verwijzing naar de image zal gaan werken — vervolgens kan de image aan dit mounting-point gekoppeld worden.

mkdir /media/test
mount -o loop test200gb.img /media/test

Eventueel kun je direct controleren of het mounten goed is gegaan met df | grep loop:

/dev/loop0      101662780   1   101662779  1% /media/test

Te weinig loop devices

Wanneer je een groot aantal images "mount" kan het zijn dat je de volgende melding krijgt:

mount: could not find any free loop device

The Linux Goblin

Om dit op te lossen kun je extra Loop devices toevoegen zoals o.a. in dit topic omschreven:

mknod -m640 /dev/loopX b 7 X
chown root:disk /dev/loopX

Zorg dat je in bovenstaand codevoorbeeld voor X het eerstvolgende vrije nummer kiest, hier kun je o.a. achter komen door ls /dev | grep loop uit te voeren.

Filecontainer vergroten / verkleinen

Om de grootte van de filecontainer aan te passen gebruik je resize2fs. Uiteraard werkt dit alleen voor ext2, ext3 of ext4 bestandssystemen:

resize2fs -p test200gb.img 300G

Filesystem state "not clean", 'Please run e2fsck first'

Wanner je een image in gebruik hebt genomen kan het zijn dat deze na verloop van tijd de status "not clean" krijgt. Wanneer je resize2fs op deze container uitvoert kan het zijn dat je de volgende melding krijgt:

Please run 'e2fsck -f test.img' first.

The Linux Goblin

Eventueel controleer je de status handmatig via dumpe2fs of tune2fs:

# Using dumpe2fs (omit "grep" part to show all details)
dumpe2fs -h test.img | grep 'Filesystem state'

# Using tune2fs give exactly the same result
tune2fs -l test.img | grep 'Filesyetem state'

Door simpelweg de instructies te volgen kun je het bestandssysteem laten controleren en eventueel direct laten repareren, maar zorg eerst dat je filecontainer niet meer gemount is:

# Unount the image first
umount /path/to/mountpoint

# The '-C 0' shows a progress bar
e2fsck -f -v -y -C 0 test.img

Houdt er rekening mee dat dit proces lang kan duren en dat je de filecontainer gedurende deze tijd niet kunt gebruiken. Op de e2fsck man page wordt aangegeven dat je de "-n" schakeloptie kunt gebruiken om alleen een controle uit te voeren. Hierdoor hoef je de filecontainer in theorie niet te unmounten, echter veranderd dit niets aan de "not clean" status én zijn de resultaten hoogst onbetrouwbaar. Dus gewoon unmounten en de tijd uitzitten.

Gereserveerde ruimte uitschakelen

Wanneer je een nieuwe container maakt, zul je zien dat de schijf al meteen een bepaald percentage in gebruik heeft. Dit komt doordat er ruimte wordt gereserveerd als een soort van 'swapping' of back-up ruimte (denk aan tijdelijke bestanden), maar voor de meeste filecontainers is dat helemaal niet nodig. Dus schakelen we dit uit met tune2fs:

tune2fs -m 0 test.img

Vrije ruimte wijkt af van grootte van image

Zelfs als je gereserveerde ruimte hebt uitgeschakeld zul je zien dat de precieze vrije ruimte in een container altijd zo'n 4% minder is dan de daadwerkelijke grootte van de container. Deze ruimte gaat o.a. verloren doordat het bestandssysteem zelf ook ruimte nodig heeft om informatie op te slaan. Het verschil kun je preciezer terugzien door het aantal vrije blocks te vergelijken met het totaal aantal blocks:

dumpe2fs -h test.img | grep -E "Block count|Free blocks"

Dit geeft een resultaat dat er als volgt uit ziet:

dumpe2fs 1.42.5 (29-Jul-2012)
Block count: 104857600
Free blocks: 101560377

Met het resultaat uit bovenstaande kunnen we de image resizen zodat deze exact 100G aan beschikbare ruimte heeft:

# Calculate the percentage of unwriteable space
# The result is .04 (4%)
echo "1 - 101560377 / 104857600" | bc -l

# Now apply this number to the size you want writeable
# The result is 104.00
echo "100 * (1 + 0.04)" | bc -l

# Apply this size to the image
resize2fs -p test.img 104G

Je zult zien dat de image nu 104GB aan ruimte in beslag neemt op de harddisk, maar een check via dumpe2fs zal bewijzen dat het precies klopt:

# Get the mount of free blocks, this should return 105622793
dumpe2fs -h test.img | grep "Free blocks"

# Now calculate blocks back to GB's, which returns little over 100G
echo "105622793 / 1024 ^ 2" | bc -l

Bronnen