14

I have just set up a Gentoo base system (which means I can boot and log in and do stuff with it now). My root partition is in an LVM2 virtual group (with a separated /boot partition). In order to boot I need to pass the parameters below to the kernel:

root=/dev/ram0 real_root=/dev/vg/rootlv init=/linuxrc dolvm

Apparently it is using an initial ramdisk to do something (I guess loading the LVM things) before mounting root. Is there a way that I can put this code into the kernel itself so that no initrd is needed? If not, how can I make the initrd myself?

It might be useful to add that I had tried compiling the kernel for non-LVM root, without initrd and it worked perfectly. Then I tried to put the whole thing under LVM and couldn't get the machine to boot (I guess it cannot deal with the LVM stuff). Then I used the genkernel tool with the --lvm option and it creates the working kernel and initrd that I am currently using.

Now I want to skip genkernel and do everything on my own, preferably without initrd so that the machine will boot somewhat faster (I don't need the flexibility anyway).

phunehehe
  • 20,240

5 Answers5

7

Simple answer: No. If you want LVM you need an initrd.

But as others have said before: LVMs don't slow your system down or do anything bad in another way, they just allow you to create an environment that allows your kernel to load and do its job.

The initrd allows your kernel to be loaded: If your kernel is on an LVM drive the whole LVM environment has to be established before the binary that contains the kernel can be loaded.

Check out the Wikipedia Entry on initrd which explains what the initrd does and why you need it.

Another note: I see your point in wanting to do things yourself but you can get your hands dirty even with genkernel. Use genkernel --menuconfig all and you can basically set everything as if you would build your kernel completely without tool support, genkernel just adds the make bzImage, make modules and make modules_install lines for you and does that nasty initrd stuff.

You can obviously build the initrd yourself as it is outlined here for initramfs or here for initrd.

tante
  • 6,350
  • 1
  • 28
  • 23
  • Well thanks for the confirmation, but you miss the part "If not, how can I make the initrd myself?" – phunehehe Sep 28 '10 at 03:52
  • Added some info and merged my other answer into this one. – tante Sep 28 '10 at 07:00
  • 9
    A minor correction: initrd is not used to load the kernel: the kernel is loaded by the bootloader (GRUB, LILO, whatever); initrd is a kind of ram-disk that provides the initial root filesystem. It should contain all binaries (e.g., kernel modules, userspace support programs) needed to actually make the system operational. This is why it is needed for an LVM root: the LVM subsystem needs to be initialized and its initialization is too complex to be conveniently done with kernel boot parameters alone; thus, the linuxrc script in initrd performs this task. – Riccardo Murri Sep 28 '10 at 07:29
  • You are of course right, I was somewhat sloppy with my phrasing. – tante Sep 28 '10 at 07:38
  • 2
    Can't upvote because of pretty big mistake in answer (initrd does not allow kernel to be loaded). – wzzrd Sep 28 '10 at 08:55
  • This is obviously incorrect. The simple answer is: Yes! You can have it compiled in the kernel. You should use the kernel without initrd. http://unix.stackexchange.com/a/2488/20498 answers this for you. – bcelary Oct 06 '15 at 12:33
5

edit: just realized you're trying to boot on LVM, I've never setup an LVM, never needed them, so probably the approach here may not work

Here is the basic rules you need to do to create an initrd-less kernel (from memory, I didn't remember exactly):

  1. Recompile your kernel, make sure to built into the kernel (IMPORTANT: not as module!):

    1. motherboard driver and harddrive driver (both under Device Drivers)
    2. filesystem driver for /, /etc/*, and /lib/modules/* (under File systems)

    Basically, the kernel needs to be able to mount the root filesystem, read the /etc/fstab, load other driver modules (if necessary), and mount other non-root filesystems to complete the rest of the booting process. If you have a more involved booting process, e.g. network booting then you need to built in those drivers as well.

  2. Disable initrd from the kernel "General setup > Initial RAM filesystems and RAM disk (initramfs/initrd)support" a.k.a. CONFIG_BLK_DEV_INITRD=n.

  3. Modify GRUB config, you no longer needs init= and realroot=, and setup root= so it points to the root filesystem device.

I think that's all. Don't forget to keep a backup kernel, and a good copy of a bootable Live CD, in case something happens.

Things that could go wrong: if you compiled in the wrong drivers or if you compile the basic drivers as a module, then the kernel cannot read the filesystem. Reboot with a fresh kernel, or with a Live CD and recompile a kernel with the correct drivers.

The only hard part is figuring out which driver is relevant to your hardware. You can use lspci and lshw to help identify your hardware. If you don't have these tools already, then emerge lshw pciutils.

Lie Ryan
  • 1,228
2

Yes, you need an initrd. Here's why:

The normal boot process starts with the bootloader, which knows just enough about your system to find the kernel and run it. (GRUB2 is smart enough to find a kernel that's located on an LVM2 or RAID partition, but GRUB1 isn't, so it's usually recommended that you create /boot as a separate partition with a simplified layout.) Once it's loaded, the kernel needs to be able to find the root filesystem, so it can start the boot process. However, LVM can't start without being triggered by some userspace tools, which exist on the root filesystem, which can't be loaded without the LVM tools, which exist on the root filesystem... ;)

To break this cycle, an initrd or initramfs is a compressed filesystem that's stored with the kernel (either in /boot, or inside the kernel itself), which contains just enough of a Linux system to start services such as LVM or MD or whatever else you want. It's a temporary filesystem, and only acts as your root filesystem long enough for the real root to be loaded.

As far as actually making one, most documentation on the topic is staggeringly obsolete - lvm2create_initrd, for instance, doesn't even work on Gentoo anymore. (I set up the same thing a few months ago, and I had to all but rewrite the script before I got a working initrd from it.) Creating your own initramfs can be fun, and it's the only way to get an absolutely minimal boot process (and learn the ins and outs about how Linux boots in the process), but it's a lot of work.

The short answer: use Dracut. It's a new framework that's being created for generating an initramfs in a mostly automated way, and it's in portage. The documentation is a bit sparse, but there's enough of it out there to figure things out, and it's by far the easiest way to get a solid initramfs, and an LVM root.

p-static
  • 717
2

While it is not possible to not use some sort of initrd it is possible to not use separate initrd files. (I have never used genkernel so I cannot give instruction for it).

For example I have set option:

CONFIG_INITRAMFS_SOURCE="/usr/src/initrd.contents"

Where /usr/src/initrd.contents in my case looks like (I have LVM+tuxonice+fbsplash):

dir /bin                                    0755 0 0
file    /bin/busybox                        /bin/busybox                        0755 0 0
file    /bin/lvm                        /sbin/lvm.static                    0755 0 0
dir /dev                                    0755 0 0
dir /dev/fb                                 0755 0 0
dir /dev/misc                               0755 0 0
dir /dev/vc                                 0755 0 0
nod /dev/console                                0600 0 0    c  5   1
nod /dev/null                               0600 0 0    c  1   3
nod /dev/snapshot                               0600 0 0    c 10 231
nod /dev/tty1                               0600 0 0    c  4   0
dir /etc                                    0755 0 0
dir /etc/splash                             0755 0 0
dir /etc/splash/natural_gentoo                      0755 0 0
dir /etc/splash/natural_gentoo/images                   0755 0 0
file    /etc/splash/natural_gentoo/images/silent-1680x1050.jpg  /etc/splash/natural_gentoo/images/silent-1680x1050.jpg  0644 0 0
file    /etc/splash/natural_gentoo/images/verbose-1680x1050.jpg /etc/splash/natural_gentoo/images/verbose-1680x1050.jpg 0644 0 0
file    /etc/splash/natural_gentoo/1680x1050.cfg        /etc/splash/natural_gentoo/1680x1050.cfg        0644 0 0
slink   /etc/splash/tuxonice                    /etc/splash/natural_gentoo              0755 0 0
file    /etc/splash/luxisri.ttf                 /etc/splash/luxisri.ttf                 0644 0 0
dir /lib64                                  0755 0 0
dir /lib64/splash                               0755 0 0
dir /lib64/splash/proc                          0755 0 0
dir /lib64/splash/sys                           0755 0 0
dir /proc                                   0755 0 0
dir /mnt                                    0755 0 0
dir /root                                   0770 0 0
dir /sbin                                   0755 0 0
file    /sbin/fbcondecor_helper                 /sbin/fbcondecor_helper                 0755 0 0
slink   /sbin/splash_helper                 /sbin/fbcondecor_helper                 0755 0 0
file    /sbin/tuxoniceui_fbsplash               /sbin/tuxoniceui_fbsplash               0755 0 0
file    /sbin/tuxoniceui_text                   /sbin/tuxoniceui_text                   0755 0 0
dir /sys                                    0755 0 0
file    /init                           /usr/src/init

And /usr/src/init is:

#!/bin/busybox ash
local X ROOT RUNLEVEL INIT PARAM
# Preliminary stuff
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
/bin/lvm vgchange -ay picard-main

# Try to resume. This never returns if it succeeds
test -e /sys/power/tuxonice/do_resume && echo 1 > /sys/power/tuxonice/do_resume
#/bin/resume

# Parse the command line for relevant options.
INIT=/sbin/init
RESCUE=""
PARAM=" "
for X in `cat /proc/cmdline`
do
        case "$X" in
                root=*) ROOT=${X#root=} ;;
                [0-6Ss]) RUNLEVEL=${X} ;;
                init=*) INIT=${X#init=} ;;
                rescue) RESCUE="rescue" ;;
        splash=*) PARAM="${PARAM} ${X}" ;;
        consol=*) PARAM="${PARAM} ${X}" ;;
        esac
done

if [ x${RESCUE} = xrescue ]
then
        busybox ash
fi

# Mount and switch root.
mount -o ro ${ROOT} /mnt
umount -f /sys || umount -l /sys
umount -f /proc || umount -l /proc

exec switch_root /mnt ${INIT} ${RUNLEVEL} ${PARAM}
1

Yes, it is.

The complications that arise from creating and handling initrds are rendered moot if you install and use grub2. The grub2 wiki http://grub.enbug.org/LVMandRAID describes how you can have your /boot on lvm with nothing more than an insmod lvm in grub.cfg, the grub configuration file, hence no need for an initrd.

grub2 now at version 1.98 but still in the experimental branch in gentoo. However it can be installed in another slot and is perfectly usable.

Enjoy!