# Controleren en mounten van disks

## Analyse

In de vorige fase van het project voegden we een boel nieuwe opdrachten toe en als resultaat biedt de rootdisk veel meer functionaliteit. Maar er ontbreekt nog steeds het een en ander. Wat er echt uitspringt is dat er geen manier is om disks te mounten. Om een read-write root bestandssysteem te krijgen, moesten we onze toevlucht nemen tot het via LILO doorgeven van de kernelparameter rw. Dit is prima voor een noodsituatie, maar in een normaal systeembootproces zou het anders gaan.

De meeste GNU/Linux distributies nemen verscheidene stappen om bestandssystemen te mounten. Het bekijken van het bootproces of het spitten in de opstartscripts van één van de populaire Linux distributies onthult de volgende reeks gebeurtenissen:

1. De kernel mount het rootbestandssysteem automatisch read-only.

2. Alle lokale bestandssystemen worden gecontroleerd op fouten.

3. root wordt opnieuw gemount als read-write, als er geen fouten in de bestandssystemen worden gedetecteerd.

4. De rest van de lokale bestandssystemen wordt gemount.

5. Netwerkbestandssystemen worden gemount.

Tot dusverre kan ons Pocket Linux systeem stap één en dat is het. Als we een professioneel uitziende boot/root disketteset willen, dan moeten we het beter doen dan één uit vijf. In deze fase van het project zullen we aan de stappen twee en drie gaan werken. De stappen vier en vijf kunnen wachten. Aangezien dit een systeem gebaseerd op diskettes is, zijn er naast root helemaal geen andere bestandssystemen te mounten.

Rekening houdend met alle bovenstaande informatie, zijn de doelen voor deze fase als volgt gedefinieerd:

- Een manier om de volledigheid van het bestandssysteem te controleren.

- De mogelijkheid om bestandssystemen te mounten.

- Een script om de controle en het mounten van lokale bestandssystemen te automatiseren.

## Ontwerp

### Vaststellen van de benodigde utility's.

We kunnen het Filesystem Hierarchy Standard (FHS) document gebruiken als hulp in het vinden van de namen van utility's die we nodig hebben en waar ze in de directorystructuur thuishoren. De FHS `/bin` directory toont `fsck` en iets met de naam `fsck.*` voor het controleren van bestandssystemen. Aangezien we voor ons doel gebruik maken van een Second Extended (ext2) bestandssysteem wordt `fsck.*` `fsck.ext2`. Het mounten van bestandssystemen wordt bewerkstelligd met de opdrachten `mount` en `umount` in de `/bin` directory. Echter de naam van een script om automatisch lokale bestandssystemen te mounten is niet te vinden. Op de meeste systemen staat dit type script in de `/etc` directory, maar ondanks dat de FHS vereisten voor `/etc` opsomt, geeft het thans geen aanbevelingen voor opstartscripts. Verscheidene GNU/Linux distributies maken gebruik van `/etc/init.d` als lokatie van opstartscripts, dus we zullen ons script om bestandssystemen te mounten daar plaatsen.

### Opsporen van de broncode

Als we Ibiblio's Linux Software Map (LSM) op http://www.ibiblio.org/pub/Linux/ doorzoeken op het trefwoord "fsck" dan krijgen we een groot aantal overeenkomsten. Aangezien we gebruik maken van het Second Extended filesystem, afgekort tot ext2, kunnen we de zoekopdracht verfijnen met het trefwoord "ext2". Beide trefwoorden aanleveren bij de LSM zoekmachine levert een package op met de naam e2fsprogs. Het LSM record bekijkend van e2fsprogs komen we erachter dat dit package de utility's `e2fsck`, `mke2fs`, `dumpe2fs`, `fsck` en meer bevat. We komen er ook achter dat het LSM record van e2fsprogs sinds 1999 niet meer is bijgewerkt. Het is vrijwel zeker dat er ergens een nieuwere versie in omloop is. Een andere goede Internetbron voor broncode is SourceForge op http://sourceforge.net. Het gebruik van het trefwoord "e2fsprogs" in de zoekmachine van SourceForge resulteert in een veel nieuwere versie van e2fsprogs.

Het was een heel avontuur om `fsck` te vinden, maar we kunnen nu verdergaan met het zoeken naar `mount` en `umount`. Een zoekopdracht op LSM levert een aantal overeenkomsten op, maar de meeste daarvan verwijzen naar diverse versies van een package genaamd util-linux. We hoeven er alleen doorheen te scrollen en de meest recente release uit te kiezen. Afgezien van slechts mount en umount wordt in het LSM record een opsomming van nog heel veel andere utility's gegeven. We zouden beslist de lijst door moeten nemen om te zien of er nog een van de andere util-linux opdrachten tevoorschijn komen in de FHS vereisten voor `/bin` en `/sbin`.

Hieronder staat een lijst met packages die we tot dusverre hebben verzameld en de utility's die overeenkomen met de FHS.

- e2fsprogs -- `fsck`, `fsck.ext2` (`e2fsck`), `mkfs.ext2` (`mke2fs`)

- util-linux -- `dmesg`, `getty` (`agetty`), `kill`, `login`, `mount`, `swapon`, `umount`

### Automatiseren van fsck en mount

Nu we `fsck` en `mount` opdrachten hebben, moeten we met een shellscript komen voor het automatisch controleren en mounten van de lokale bestandssystemen. Een makkelijke manier om dit te doen zou zijn om een kort, tweeregelig script te schrijven dat `fsck` en dan `mount` aanroept. Maar wat als de bestandssystemen niet zuiver zijn? Het systeem zou beslist geen beschadigd bestandssysteem moeten proberen te mounten. Daarom moeten we een middel zien te verzinnen hoe de status van de bestandssystemen vast te stellen voordat ze worden gemount. De manpage van `fsck` geeft inzicht in hoe dit kan worden bewerkstelligd met behulp van returncodes. Een returncode van nul of één betekent dat het bestandssysteem in orde is en twee of groter betekent dat een of andere handmatige tussenkomst nodig is. Een simpel if-then statement zou de returncode van `fsck` kunnen evalueren om vast te stellen of het bestandssysteem wel of niet kan worden gemount. Voor hulp bij het schrijven van shellscripts kunnen we ons wenden tot de BASH(1) manpage en de Advanced BASH Scripting Guide (http://www.tldp.org/guides.html). Beide referenties zijn vrij verkrijgbaar vanaf het Linux Documentatie Project.

### Bestandsafhankelijkheden

Wat we als laatste nog moeten doen is uitzoeken of er afgezien van de binary's nog andere bestanden nodig zijn. We leerden het gebruik van `ldd` om te controleren op library afhankelijkheden in de laatste fase van het project en we zullen het ook gebruiken om in deze fase de utility's te controleren. Er zijn ook nog een aantal andere bestanden die `fsck` en `mount` nodig zullen hebben en de manpages fsck(8) en mount(8) geven wat inzicht in welke bestanden dit zijn. Het gaat om `/etc/fstab` waarin devices worden opgesomd met bijbehorende mountpoints, `/etc/mtab` waarin wordt bijgehouden wat is gemount en de devicebestanden die de diverse disks voorstellen. We zullen die voor de juiste werking op moeten nemen.

Het `/etc/fstab` bestand is slechts een simpel tekstbestand dat met iedere willekeurige editor kan worden aangemaakt. We zullen een regel nodig hebben voor het root bestandssysteem en voor het proc bestandssysteem. De reden voor de regel met het proc bestandssysteem is dat we `/etc/mtab` als een symlink die verwijst naar `/proc/mounts` aan kunnen maken. Het bestand `/proc/mounts` bevat bijna exact dezelfde informatie als het traditionele `/etc/mtab` bestand. We moeten er gewoon voor zorgen dat het proc bestandssysteem voor ieder ander wordt gemount. Het enige dat er overblijft is de aanmaak van devicebestanden. We zullen `/dev/ram0` nodig hebben, omdat daar het root bestandssysteem is te vinden. We hebben ook `/dev/fd0` nodig om andere diskettes te mounten en `/dev/null`.

## Constructie

### Installeer utility's uit e2fsprogs

    bash# cd /usr/src/e2fsprogs-1.29
    bash# ./configure --host=i386-pc-linux-gnu
    bash# make
    bash# cd e2fsck
    bash# cp e2fsck.shared ~/fase/sbin/e2fsck
    bash# ln -s e2fsck ~/fase/sbin/fsck.ext2
    bash# cd ../misc
    bash# cp fsck mke2fs ~/fase/sbin
    bash# ln -s mke2fs ~/fase/sbin/mkfs.ext2

### Installeer utility's uit util-linux

    bash# cd /usr/src/util-linux-2.11u

Gebruik een teksteditor om de volgende wijzigingen aan te brengen in `MCONFIG`:

- Wijzig "CPU=$(shell uname -m)" in "CPU=i386"

- Wijzig "HAVE_SHADOW=yes" in "HAVE_SHADOW=no"

    bash# ./configure
    bash# make
    bash# cp disk-utils/mkfs ~/fase/sbin
    bash# cp fdisk/fdisk ~/fase/sbin
    bash# cp login-utils/agetty ~/fase/sbin
    bash# ln -s agetty ~/fase/sbin/getty
    bash# cp login-utils/login ~/fase/bin
    bash# cp misc-utils/kill ~/fase/bin
    bash# cp mount/mount ~/fase/bin
    bash# cp mount/umount ~/fase/bin
    bash# cp mount/swapon ~/fase/sbin
    bash# cp sys-utils/dmesg ~/fase/bin

### Controleer op library benodigdheden

    bash# ldd ~/fase/bin/* | more
    bash# ldd ~/fase/sbin/* | more
    bash# ls ~/fase/lib

Alle afhankelijkheden onthuld door de opdracht `ldd`, zijn voor library's die reeds aanwezig zijn in het fasegebied, dus er hoeft niets nieuws te worden gekopieerd.

### Strip binary's om ruimte te besparen

    bash# strip ~/fase/bin/*
    bash# strip ~/fase/sbin/*

### Maak extra devicebestanden aan

    bash# mknod ~/fase/dev/ram0 b 1 0
    bash# mknod ~/fase/dev/fd0 b 2 0
    bash# mknod ~/fase/dev/null c 1 3

### Maak de bestanden mtab en fstab aan

    bash# cd ~/fase/etc
    bash# ln -s /proc/mounts mtab

Gebruik een editor als vi, emacs of pico om het volgende bestand aan te maken het sla het op als `~/fase/etc/fstab`.

    proc		/proc	proc	noauto		0	0
    /dev/ram0	/	ext2	defaults	1	1

### Schrijf een script om het proc bestandssysteem te mounten

    bash# mkdir ~/fase/etc/init.d
    bash# cd ~/fase/etc/init.d

Gebruik een editor om het volgende shellscript aan te maken en sla het op als `~/fase/etc/init.d/proc_fs`:

    #!/bin/sh
    #
    # proc_fs - mount het proc bestandssysteem
    #
    PATH=/sbin:/bin ; export PATH

    mount -t proc proc /proc
    #
    # einde van proc_fs

### Schrijf een script dat lokale bestandssystemen controleert en mount

Gebruik een editor om het volgende shellscript aan te maken en sla het op als `~/fase/etc/init.d/local_fs`:

    #!/bin/sh
    #
    # local_fs - controleer en mount lokale bestandssystemen
    #
    PATH=/sbin:/bin ; export PATH

    fsck -ATCp
    if [ $(($?)) -gt $((1)) ]; then
      echo "Filesystem errors still exist!  Manual intervention required."
      /bin/sh
    else
      echo "Remounting / as read-write."
      mount -o remount,rw /
      echo "Mounting local filesystems."
      mount -a
    fi
    #
    # einde van local_fs

Stel uitvoerpermissies in op de scripts.

    bash# chmod +x proc_fs
    bash# chmod +x local_fs

### Maak een gecomprimeerd rootdiskimage aan

    bash# cd /
    bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
    bash# mke2fs -m0 /dev/ram7
    bash# mount /dev/ram7 /mnt
    bash# cp -dpR ~/fase/* /mnt
    bash# umount /dev/ram7
    bash# dd if=/dev/ram7 of=~/phase4-image bs=1k
    bash# gzip -9 ~/phase4-image

### Schrijf het rootdiskimage naar diskette

Doe de diskette met het label "rootdisk" in het diskettestation fd0.

    bash# dd if=~/phase4-image.gz of=/dev/fd0 bs=1k

## Implementatie

### Systeemstart

Start het systeem volgens de volgende procedure:

- Boot de PC met behulp van de diskette met het label "bootdisk".

- Typ `bootdisk init=/bin/sh` achter de LILO-prompt.

- Doe de recent aangemaakte rootdisk in het diskettestation wanneer dit wordt aangegeven.

De uitvoer zou het onderstaand voorbeeld moeten weerspiegelen:

    boot: bootdisk init=/bin/sh
    Loading bootdisk
    Uncompressing Linux... Ok, booting kernel.
    ..
    .. [diverse kernelmeldingen]
    ..
    VFS: Insert root floppy to be loaded into RAM disk and press ENTER
    RAMDISK: Compressed image found at block 0
    VFS: Mounted root (ext2 filesystem) readonly.
    Freeing unused kernel memory: 178k freed
    # _

### Test proc_fs en local_fs scripts

Voer de scripts uit door de volgende opdrachten achter de shellprompt in te tikken:

    bash# PATH=/sbin:/bin:/etc/init.d ; export PATH
    bash# proc_fs
    bash# cat /etc/mtab
    bash# local_fs
    Remounting / as read-write.
    Mounting local filesystems
    bash# df

De schermuitvoer zou er ongeveer uit moeten zien als in onderstaand voorbeeld als alles naar behoren werkt.

    bash# PATH=/sbin:/bin:/etc/init.d ; export PATH
    bash# proc_fs
    bash# cat /etc/mtab
    /dev/root / ext2 ro 0 0
    proc /proc proc rw 0 0
    bash# local_fs
    /dev/ram0: clean 74/1024 files 3178/4096 blocks
    bash# df
    Filesystem      1k-blocks       Used Available Use% Mounted on
    /dev/root       3963            3045 918        77% /

### Maak extra bestandssystemen aan en mount deze

Verwijder de rootdisk diskette en doe een lege diskette met het label "home" in het diskettestation. Typ dan de volgende opdrachten:

    bash# mkfs /dev/fd0
    bash# fsck /dev/fd0
    bash# mount /dev/fd0 /home
    bash# mkdir /home/floyd
    bash# cd /home/floyd
    bash# echo "Goodbye cruel world." > goodbye.txt
    bash# cat goodbye.txt

### Systeem afsluiten

    bash# cd /
    bash# umount /dev/fd0
    bash# sync

Verwijder de diskette uit fd0 en herstart het systeem met CTRL-ALT-DELETE.