Mainpage
Searchform
History
Versions
Categories
Contents
Deutsch
SuSE Linux: Versions since 6.3
When the Linux kernel is loaded and has mounted the root filesystem ('/'), programs can be executed and additional kernel modules may be loaded to add additional functionality.
But in order to be actually able to mount the root filesystem, some conditions have to be met: the kernel needs the appropriate drivers to access the device containing the root filesystem (specially SCSI drivers). Additionally, the kernel needs the code that enables it to read the filesystem (ext2, reiserfs, romfs etc.). Furthermore, the root filesystem could be encrypted, necessitating prompting the user for key/password.
Singling out the problem of the SCSI drivers, various solutions come to mind: The kernel could contain all possible drivers. Problematic, as some drivers don't play along well with others; furthermore the kernel would get rather large. Another possibility would be providing different kernels that each only contain one or very few SCSI drivers. This path also has its problems, as this would sharply increase the number of different kernels needed. A problem that gets even more acute by the need to supply differently optimized kernels (Pentium optimized, SMP).
The approach of loading the SCSI drivers as modules leads to the general problem, which is countered by the concept of an initial ramdisk: The creation of a method to run userspace programs even before the root filesystem is mounted.
The initial ramdisk (also called initdisk or initrd) solves the problems
detailed above. The Linux kernel offers the possibility of loading a (small)
filesystem into a ramdisk and executing programs from there before the
actual root filesystem gets mounted. The loading of the initrd is done by
the bootloader (LILO
, loadlin
etc.); all these
bootloaders only need BIOS routines to load data from the boot media. If the
bootloader can load the kernel, it can load the initial ramdisk just as
well. So special drivers are not necessary.
The bootloader loads the kernel and the initrd into memory and starts the kernel, telling it that an initrd is present and where in memory the kernel will find it.
If the initrd was compressed (which is typically the case), the kernel
decompresses and mounts it as a temporary root filesystem. After having done
so, a special program named linuxrc
, contained in the initrd, is executed.
This program is able to perform all tasks necessary to enable the kernel to
mount the real root filesystem. When linuxrc
terminates, the (temporary)
initrd is unmounted and booting continues by mounting the real root
filesystem. The mounting of the initrd and the execution of linuxrc
may thus be
viewed as a short intermezzo during the normal boot procedure.
If the initrd can't be unmounted (which should be regarded as an error), the kernel tries to change its mountpoint to /initrd. Is this doesn't exist, an error message is displayed. In this case the system is fully functional, but the memory occupied by the initrd can never be freed and thus remains unavailable.
The program linuxrc has only to meet the following requirements: It has to
have the name 'linuxrc' and it has to be in the root directory of the
initrd. Besides that, the kernel has to be able to execute it. This means that
linuxrc may well be linked dynamically, but then of course the shared
libraries have to be completely available under /lib in the initrd.
Additionally, linuxrc may also be a shell script, obviating the need of a
shell, available under /bin. In short, the initrd must contain a minimal
Linux system that allows the program linuxrc to be executed. The
installation of SuSE Linux uses a statically linked linuxrc in order to keep
the initrd as small as possible (space on the boot floppies is scarce).
Linuxrc
is run with root privileges.
As soon as linuxrc
terminates, the initrd is unmounted and
discarded and booting continues normally with the kernel mounting the real
root filesystem. What gets mounted as the root filesystem may be changed by
linuxrc
. To do so, linuxrc
only has to mount the
/proc filesystem and write the value of the real root filesystem in
numerical form to /proc/sys/kernel/real-root-dev.
Most bootloaders (specially LILO
, loadlin
and
syslinux
) are able to deal with initrd. The bootloaders are
advised to use an initrd like this:
initrd=/boot/initdisk.gz
The file "/boot/initdisk.gz" is the initial ramdisk. It may (but needn't) be compressed.
loadlin initrd=C:\linux\initdisk.gz
By adding the following line to syslinux.cfg
append initrd=initdisk.gz
The initrd has been used for the installation for quite some time now: The
user is able to load modules in linuxrc
and enter the information (such as
the source medium, for example) needed for the installation. Linuxrc
then
starts YaST, which does the installation. When YaST has done its work, it
tells linuxrc
where the root filesystem of the newly installed system lies.
Linuxrc
writes this value to /proc, exits, and the kernel boots the freshly
installed system.
So during an installation of SuSE Linux you boot the system that has just been installed. A real reboot only happens if the currently running kernel is incompatible with the modules installed in the system. As SuSE Linux currently uses a uni-processor kernel for installation, this currently only happens if an SMP kernel and matching modules were installed. In order to be able to use all modules, the freshly installed SMP kernel has to be booted.
In the past, YaST offered more than 40 kernels for installation, where those kernels mostly differed in the specific SCSI driver they contained. This was necessary in order to be able to mount the root filesystem after booting. Additional drivers could later be loaded as modules.
As we now also offer optimized kernels, this concept wasn't supportable anymore (it would necessitate far more than 100 kernel images).
Therefore an initrd is now also used to start the normal system. The
mechanism is similiar to during an installation, but the linuxrc
used here
is only a simple shell script, whose only task is to load certain modules.
Typically, this is just one module, namely the SCSI driver needed to access
the root filesystem.
The creation of an initrd is done via the script mk_initrd
. In SuSE Linux,
the modules to load are specified through the variable INITRD_MODULES
in
/etc/rc.config. After an installation this variable is preset to the correct
values (as linuxrc
knows which modules got loaded). One should note that
the modules get loaded in exactly the order in which they appear in
INITRD_MODULES
. This is specially important if more than one SCSI driver is
used, as otherwise the disk names would change. Strictly speaking, it would
suffice to only load the SCSI driver needed for accessing the root
filesystem. But as the automatic loading of additional SCSI drivers is not
without pitfalls (how should it be triggered when disks are also attached to
the second SCSI controller?), we load all SCSI drivers used during the
installation by means of the initrd.
The current mk_initrd
checks if a SCSI driver is actually needed to access
the root file system. If you call mk_initrd
on a system where / is on an
EIDE disk, it won't create an initrd, as it isn't necessary because SuSE
kernels always contain the EIDE drivers. But as the number of special EIDE
controllers being offered is increasing, its foreseeable that in the future
an initrd will be used for booting the installed system also in these
cases.
LILO
notes the location of the file in
its map file), LILO
must be reinstalled after every change to the
initrd! After doing mk_initrd
, it's therefor also necessary to
do a lilo
!If you compile your own kernel, the following frequent problem may occur: out of habit, the SCSI driver is compiled into the kernel but the existing initrd stays unmodified. When booting, the following happens: The kernel already contains the SCSI driver, the harware is correctly detected. Now the initrd tries to load the same driver, but as a module; with some SCSI drivers (most notably the aic7xxx) this leads to system lockup. Strictly speaking, this is a kernel bug (it should be impossible to load an already exiting driver additionally as module), but it's a known problem, although in another context (serial driver).
There are several solutions to this problem: either the driver is
configured as a module (then it will get loaded by the initrd correctly), or
the entry for the initrd is removed from /etc/lilo.conf. Equivalent to the
latter solution would be to remove the driver from INITRD_MODULES
and then
call mk_initrd
, which notices that no initrd is needed.
If parameters have to be passed to a given module in order to get it loaded, these get lost after the installation; they are not entered into the initrd used for booting the system. Luckily, only very few SCSI drivers require parameters. Whoever is confronted by this problem has to boot his system with the installation boot floppy and build himself a kernel containing the SCSI drivers.
The problem has been solved in the meantime. In SuSE 6.4, module parameters will also be used when starting a system from an initrd.
If network drivers got loaded during the installation, these will also be
entered in INITRD_MODULES
and thus loaded in the initrd when booting the
system. While this isn't an error in itself, it may lead to problems in some
cases:
eth0=ne
ist set correctly in /etc/modules.conf.
2. Forcing certain configurations: If it's required to force a network card into full-duplex mode or force the use of a certain media type (e.g. by passing options=xxx to the tulip driver), this will fail, because - as stated above - the parameters used during installation are not used later on.
This problem has also been solved. First, module parameters will be reused
correctly in the future and secondly, the installation linuxrc
will only
enter SCSI drivers in INITRD_MODULES
.
/usr/src/linux/Documentation/ramdisk.txt
/usr/src/linux/Documentation/initrd.txt
See also:
Keywords: BOOT, INITRD, RAMDISK, VFS, SCSI, LILO, LOADLIN
Categories:
LILO
Mainpage
Searchform
History
Versions
Categories
Contents
Deutsch