mirror of https://github.com/tLDP/LDP
513 lines
21 KiB
XML
513 lines
21 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter id="phase4">
|
|
<title>Checking and Mounting Disks</title>
|
|
|
|
<sect1>
|
|
<title>Analysis</title>
|
|
|
|
<para>In the previous chapter we added many new commands by installing
|
|
coreutils and as a result the root disk has a lot more functionality. But
|
|
there are still a few things lacking. One thing that really stands out is
|
|
that there was no way to mount disks. In order to get a read-write root
|
|
filesystem we had to resort to passing the <parameter>rw</parameter>
|
|
kernel parameter at the <prompt>grub></prompt> prompt. This is fine for
|
|
an emergency situation, but a normal system boot process should do things
|
|
differently.</para>
|
|
|
|
<para>Most GNU/Linux distributions take several steps to mount
|
|
filesystems. Watching the boot process or digging into the startup scripts
|
|
on one of the popular Linux distributions reveals the following sequence
|
|
of events:</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>The kernel automatically mounts the root filesystem as
|
|
read-only.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>All local filesystems are checked for errors.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If filesystems are clean, root is remounted as
|
|
read-write.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The rest of the local filesystems are mounted.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Network filesystems are mounted.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>So far our Pocket Linux system can do step one and that is it. If we
|
|
want to have a professional looking boot / root diskset we will have to do
|
|
better than one out of five. In this phase of the project we will work on
|
|
steps two and three. Steps four and five can wait. Since this is a
|
|
diskette-based system, there really are no other filesystems to mount
|
|
besides root.</para>
|
|
|
|
<para>Taking into account all of the above information, the goals for this
|
|
phase are defined as follows:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>A way to check filesystem integrity.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>The ability to mount filesystems.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A script to automate checking and mounting of local
|
|
filesystems.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Design</title>
|
|
|
|
<sect2>
|
|
<title>Determining necessary utilities.</title>
|
|
|
|
<para>We can use the Filesystem Hierarchy Standard (FHS) document to
|
|
help find the names of utilities we need and where they reside in the
|
|
directory structure. The FHS <filename>/sbin</filename> directory lists
|
|
<command>fsck</command> and something called <command>fsck.*</command>
|
|
for checking filesystems. Since we are using a Second Extended (ext2)
|
|
filesystem the <command>fsck.*</command> becomes
|
|
<command>fsck.ext2</command> for our purposes. Mounting filesystems is
|
|
done using the commands <command>mount</command> and
|
|
<command>umount</command> in the <filename>/bin</filename> directory.
|
|
However, the name of a script to automatically mount local filesystems
|
|
cannot be found. On most systems this type of script is in the
|
|
<filename>/etc</filename> directory, but while FHS does list
|
|
requirements for <filename>/etc</filename>, it does not currently make
|
|
recommendations for startup scripts. Several GNU/Linux distributions use
|
|
<filename>/etc/init.d</filename> as the place to hold startup scripts so
|
|
we will put our filesystem mounting script there.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Finding source code</title>
|
|
|
|
<para>In the previous chapter we used manpages to help us find source
|
|
code. In this chapter we will use a tool called the Linux Software Map
|
|
(LSM). LSM is a database of GNU/Linux software that tracks such things
|
|
as package name, author, names of binaries that make up the package and
|
|
download sites. Using an LSM search engine we can locate packages using
|
|
command names as keywords.</para>
|
|
|
|
<para>If we search Ibiblio's Linux Software Map (LSM) at <ulink
|
|
url="http://www.ibiblio.org/pub/Linux/">http://www.ibiblio.org/pub/Linux/</ulink>
|
|
for the keyword "fsck" we get a large number of matches. Since we are
|
|
using a Second Extended filesystem, called ext2 for short, we can refine
|
|
the search using "ext2" as a keyword. Supplying both keywords to the LSM
|
|
search engine comes up with a package called e2fsprogs. Looking at the
|
|
LSM entry for e2fsprogs we find out that this package contains the
|
|
utilities <command>e2fsck</command>, <command>mke2fs</command>,
|
|
<command>dumpe2fs</command>, <command>fsck</command> and more. We also
|
|
find out that the LSM entry for e2fsprogs has not been updated for a
|
|
while. There is almost certainly a newer version out there somewhere.
|
|
Another good Internet resource for source code is SourceForge at <ulink
|
|
url="http://sourceforge.net/">http://sourceforge.net/</ulink>. Using the
|
|
keyword "e2fsprogs" in the SourceForge search engine results in a much
|
|
newer version of e2fsprogs.</para>
|
|
|
|
<para>Finding <command>fsck</command> was quite an adventure, but now we
|
|
can move on to finding <command>mount</command> and
|
|
<command>umount</command>. A search on LSM comes up with a number of
|
|
matches, but most of them point to various versions of a package called
|
|
util-linux. All we have to do is scroll through and pick the most recent
|
|
release. The LSM entry for util-linux lists a lot of utilities besides
|
|
just mount and umount. We should definitely scan through the list to see
|
|
if any of the other util-linux commands show up in the FHS requirements
|
|
for <filename>/bin</filename> and <filename>/sbin</filename>.</para>
|
|
|
|
<para>Below is a list of packages we have gathered so far and the
|
|
utilities that match up with FHS.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>e2fsprogs -- <command>fsck</command>,
|
|
<command>fsck.ext2</command> (<command>e2fsck</command>),
|
|
<command>mkfs.ext2</command> (<command>mke2fs</command>)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>util-linux -- <command>dmesg</command>,
|
|
<command>getty</command> (<command>agetty</command>),
|
|
<command>kill</command>, <command>login</command>,
|
|
<command>mount</command>, <command>swapon</command>,
|
|
<command>umount</command></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Automating fsck and mount</title>
|
|
|
|
<para>Now that we have <command>fsck</command> and
|
|
<command>mount</command> commands we need to come up with a shell script
|
|
to automate checking and mounting the local filesystems. An easy way to
|
|
do this would be to write a short, two line script that calls
|
|
<command>fsck</command> and then <command>mount</command>. But, what if
|
|
the filesystems are not clean? The system should definitely not try to
|
|
mount a corrupted filesystem. Therefore we need to devise a way of
|
|
determining the status of the filesystems before mounting them. The
|
|
manpage for <command>fsck</command> gives some insight into how this can
|
|
be accomplished using return codes. Basically, if
|
|
<command>fsck</command> returns a code of zero or one it means the
|
|
filesystem is okay and a return code of two or greater means some kind
|
|
of manual intervention is needed. A simple if-then statement could
|
|
evaluate the <command>fsck</command> return code to determine whether or
|
|
not the filesystem should be mounted. For help on writing shell scripts
|
|
we can turn to the BASH(1) manpage and the
|
|
Advanced-BASH-Scripting-Guide. Both references are freely available from
|
|
the Linux Documentation Project web site at <ulink
|
|
url="http://www.tldp.org/">http://www.tldp.org/</ulink>.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>File dependencies</title>
|
|
|
|
<para>The last thing to do is to figure out if any other files besides
|
|
the binaries are needed. We learned about using <command>ldd</command>
|
|
to check for library dependencies in the last phase of the project and
|
|
we will use it to check the utilities in this phase too. There are also
|
|
some other files that <command>fsck</command> and
|
|
<command>mount</command> will need and the fsck(8) and mount(8) manpages
|
|
give some insight into what those files are. There is
|
|
<filename>/etc/fstab</filename> that lists devices and their mount
|
|
points, <filename>/etc/mtab</filename> that keeps track of what is
|
|
mounted, and a number of <filename>/dev</filename> files that represent
|
|
the various disks. We will need to include all of these to have
|
|
everything work right.</para>
|
|
|
|
<sect3>
|
|
<title>/etc/fstab</title>
|
|
|
|
<para>The <filename>/etc/fstab</filename> file is just a simple text
|
|
file that can be created with any editor. We will need an entry for
|
|
the root filesystem and for the proc filesystem. Information about the
|
|
format of this file can be found in the fstab(5) manpage or by looking
|
|
at the <filename>/etc/fstab</filename> file on any of the popular
|
|
GNU/Linux distributions.</para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>/etc/mtab</title>
|
|
|
|
<para>The <filename>/etc/mtab</filename> file presents a unique
|
|
challenge, because it does not contain static information like
|
|
<filename>fstab</filename>. The <filename>mtab</filename> file tracks
|
|
mounted filesystems and therefore its contents change from time to
|
|
time. We are particularly interested in the state of
|
|
<filename>mtab</filename> when the system first starts up, before any
|
|
filesystems are mounted. At this point <filename>/etc/mtab</filename>
|
|
should be empty so we will need to configure a startup script to
|
|
create an empty <filename>/etc/mtab</filename> before any filesystems
|
|
are mounted. But it is not possible to create any files in the
|
|
<filename>/etc</filename> directory because <filename>/</filename> is
|
|
read-only at startup. This creates a paradox. We cannot create an
|
|
empty <filename>mtab</filename>, because the <filename>/</filename>
|
|
filesystem is not mounted as writable and we should not mount any
|
|
filesystems until we have created an empty <filename>mtab</filename>.
|
|
In order to sidestep this problem we need to do the following:</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>Remount <filename>/</filename> as read-write, but use the
|
|
<option>-n</option> option so that <command>mount</command> does
|
|
not attempt to write an entry to <filename>/etc/mtab</filename>
|
|
which is read-only at this point.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Create an empty <filename>/etc/mtab</filename> file now that
|
|
the filesystem is writable.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Remount <filename>/</filename> as read-write again, this
|
|
time using the <option>-f</option> option so that an entry is
|
|
written into <filename>/etc/mtab</filename>, but
|
|
<filename>/</filename> is not actually mounted a second
|
|
time.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Device files</title>
|
|
|
|
<para>The only thing left to do is to create device files. We will
|
|
need <filename>/dev/ram0</filename>, because that is where the root
|
|
filesystem is located. We also need <filename>/dev/fd0</filename> to
|
|
mount other floppy disks and <filename>/dev/null</filename> for use by
|
|
some of the system commands.</para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Construction</title>
|
|
|
|
<sect2>
|
|
<title>Install utilities from e2fsprogs</title>
|
|
|
|
<para>Download the e2fsprogs source code package from <ulink
|
|
url="http://sourceforge.net/projects/e2fsprogs/">http://sourceforge.net/projects/e2fsprogs/</ulink></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /usr/src/e2fsprogs-1.35
|
|
<prompt>bash#</prompt> export CC="gcc -mcpu=i386"
|
|
<prompt>bash#</prompt> ./configure --host=i386-pc-linux-gnu
|
|
<prompt>bash#</prompt> make
|
|
<prompt>bash#</prompt> cd e2fsck
|
|
<prompt>bash#</prompt> cp e2fsck.shared ~/staging/sbin/e2fsck
|
|
<prompt>bash#</prompt> ln -s e2fsck ~/staging/sbin/fsck.ext2
|
|
<prompt>bash#</prompt> cd ../misc
|
|
<prompt>bash#</prompt> cp fsck mke2fs ~/staging/sbin
|
|
<prompt>bash#</prompt> ln -s mke2fs ~/staging/sbin/mkfs.ext2</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Install utilities from util-linux</title>
|
|
|
|
<para>Get the latest util-linux source from <ulink
|
|
url="ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/">ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/</ulink></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /usr/src/util-linux-2.12h</programlisting></para>
|
|
|
|
<para>Use a text editor to make the following changes to
|
|
<filename>MCONFIG</filename>:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Change "CPU=$(shell uname -m)" to "CPU=i386"</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Change "HAVE_SHADOW=yes" to "HAVE_SHADOW=no"</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ./configure
|
|
<prompt>bash#</prompt> make
|
|
<prompt>bash#</prompt> cp disk-utils/mkfs ~/staging/sbin
|
|
<prompt>bash#</prompt> cp fdisk/fdisk ~/staging/sbin
|
|
<prompt>bash#</prompt> cp login-utils/agetty ~/staging/sbin
|
|
<prompt>bash#</prompt> ln -s agetty ~/staging/sbin/getty
|
|
<prompt>bash#</prompt> cp login-utils/login ~/staging/bin
|
|
<prompt>bash#</prompt> cp misc-utils/kill ~/staging/bin
|
|
<prompt>bash#</prompt> cp mount/mount ~/staging/bin
|
|
<prompt>bash#</prompt> cp mount/umount ~/staging/bin
|
|
<prompt>bash#</prompt> cp mount/swapon ~/staging/sbin
|
|
<prompt>bash#</prompt> cp sys-utils/dmesg ~/staging/bin</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Check library requirements</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ldd ~/staging/bin/* | more
|
|
<prompt>bash#</prompt> ldd ~/staging/sbin/* | more
|
|
<prompt>bash#</prompt> ls ~/staging/lib</programlisting></para>
|
|
|
|
<para>All of the dependencies revealed by the <command>ldd</command>
|
|
command are for libraries already present in the staging area so there
|
|
is no need to copy anything new.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Strip binaries to save space</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> strip ~/staging/bin/*
|
|
<prompt>bash#</prompt> strip ~/staging/sbin/*</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create additional device files</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> mknod ~/staging/dev/ram0 b 1 0
|
|
<prompt>bash#</prompt> mknod ~/staging/dev/fd0 b 2 0
|
|
<prompt>bash#</prompt> mknod ~/staging/dev/null c 1 3</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create the fstab and mtab files</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd ~/staging/etc
|
|
</programlisting></para>
|
|
|
|
<para>Use an editor like vi, emacs or pico to create the following file
|
|
and save it as <filename>~/staging/etc/fstab</filename>.</para>
|
|
|
|
<para><programlisting>proc /proc proc defaults 0 0
|
|
/dev/ram0 / ext2 defaults 1 1</programlisting></para>
|
|
|
|
<para>Create an empty mtab file.</para>
|
|
|
|
<programlisting><prompt>bash#</prompt> echo -n >mtab</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Write a script to check and mount local filesystems</title>
|
|
|
|
<para>Use an editor to create the following shell script and save it as
|
|
<filename>~/staging/etc/init.d/local_fs</filename>:</para>
|
|
|
|
<para><programlisting>#!/bin/sh
|
|
#
|
|
# local_fs - check and mount local filesystems
|
|
#
|
|
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 -n -o remount,rw /
|
|
echo -n >/etc/mtab
|
|
mount -f -o remount,rw /
|
|
echo "Mounting local filesystems."
|
|
mount -a -t nonfs,nosmbfs
|
|
fi
|
|
#
|
|
# end of local_fs</programlisting></para>
|
|
|
|
<para>Set execute permissions on the script.<programlisting><prompt>bash#</prompt> chmod +x local_fs</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create a compressed root disk image</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /
|
|
<prompt>bash#</prompt> dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
|
|
<prompt>bash#</prompt> mke2fs -m0 /dev/ram7 4096
|
|
<prompt>bash#</prompt> mount /dev/ram7 /mnt
|
|
<prompt>bash#</prompt> cp -dpR ~/staging/* /mnt
|
|
<prompt>bash#</prompt> umount /dev/ram7
|
|
<prompt>bash#</prompt> dd if=/dev/ram7 of=~/phase4-image bs=1k count=4096
|
|
<prompt>bash#</prompt> gzip -9 ~/phase4-image</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Write the root disk image to floppy</title>
|
|
|
|
<para>Insert the diskette labeled "root disk" into drive fd0.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> dd if=~/phase4-image.gz of=/dev/fd0 bs=1k</programlisting></para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Implementation</title>
|
|
|
|
<sect2>
|
|
<title>System startup</title>
|
|
|
|
<para>Start the system using the following procedure:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Boot the PC using the floppy labeled "boot disk".</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>At the <prompt>grub></prompt> prompt, type the usual kernel
|
|
and boot commands, but without the <parameter>rw</parameter>
|
|
parameter this time. In other words, type <userinput>kernel
|
|
(fd0)/boot/vmlinuz init=/bin/sh root=/dev/fd0 load_ramdisk=1
|
|
prompt_ramdisk=1</userinput>, press <keycap>Enter</keycap> then type
|
|
<userinput>boot</userinput> and press <keycap>Enter</keycap>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Put in the recently created root disk when prompted.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The output should resemble the example below:</para>
|
|
|
|
<screen>GNU GRUB version 0.95
|
|
|
|
grub> kernel (fd0)/boot/vmlinuz init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1
|
|
[Linux-bzImage, setup=0xc00, size=0xce29b]
|
|
|
|
grub> boot
|
|
|
|
Linux version 2.4.26
|
|
..
|
|
.. [various kernel messages]
|
|
..
|
|
VFS: Insert root floppy disk 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
|
|
# _</screen>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Test the local_fs script</title>
|
|
|
|
<para>Run the script by typing the following commands at the shell
|
|
prompt:</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> PATH=/sbin:/bin:/etc/init.d ; export PATH
|
|
<prompt>bash#</prompt> cat /etc/mtab
|
|
<prompt>bash#</prompt> local_fs
|
|
<prompt>bash#</prompt> cat /etc/mtab
|
|
<prompt>bash#</prompt> df</programlisting></para>
|
|
|
|
<para>If everything is working properly, then the screen output should
|
|
look something like the example below.</para>
|
|
|
|
<para><screen><prompt>bash#</prompt> PATH=/sbin:/bin:/etc/init.d ; export PATH
|
|
<prompt>bash#</prompt> cat /etc/mtab
|
|
<prompt>bash#</prompt> local_fs
|
|
/dev/ram0: clean 74/1024 files 3178/4096 blocks
|
|
Remounting / as read-write.
|
|
Mounting local filesystems.
|
|
<prompt>bash#</prompt> cat /etc/mtab
|
|
/dev/ram0 / ext2 rw 0 0
|
|
proc /proc proc rw 0 0
|
|
<prompt>bash#</prompt> df
|
|
Filesystem 1k-blocks Used Available Use% Mounted on
|
|
/dev/ram0 3963 3045 918 77% /
|
|
</screen></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create and mount additional filesystems</title>
|
|
|
|
<para>Procure a blank floppy disk and label it as "home". Remove the
|
|
root disk floppy and insert the "home" diskette. Type the following
|
|
commands:</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> mkfs -t ext2 /dev/fd0
|
|
<prompt>bash#</prompt> fsck /dev/fd0
|
|
<prompt>bash#</prompt> mount /dev/fd0 /home
|
|
<prompt>bash#</prompt> mkdir /home/floyd
|
|
<prompt>bash#</prompt> cd /home/floyd
|
|
<prompt>bash#</prompt> echo "Goodbye cruel world." > goodbye.txt
|
|
<prompt>bash#</prompt> cat goodbye.txt</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>System shutdown</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /
|
|
<prompt>bash#</prompt> umount /home</programlisting></para>
|
|
|
|
<para>Remove the diskette from fd0 and restart the system using
|
|
<keycap>CTRL</keycap>-<keycap>ALT</keycap>-<keycap>DELETE</keycap>.</para>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter> |