38

My system boots OK with this in my GRUB 2 config:

linux   /bzImage root=/dev/sda2 init=/usr/lib/systemd/systemd ro

But if I replace /dev/sda2 with the corresponding UUID:

linux   /bzImage root=UUID=666c2eee-193d-42db-a490-4c444342bd4e init=/usr/lib/systemd/systemd ro

then it fails during boot:

kernel panic - not syncing: VFS: unable to mount root fs on unknown-block(0,0)

The UUID appears to be correct:

# blkid
/dev/sda1: UUID="97ac3744-39de-4d6d-9a81-e3a3ea08a8bb" TYPE="ext2" 
/dev/sda2: UUID="666c2eee-193d-42db-a490-4c444342bd4e" TYPE="ext4" 

Why doesn't it work? Is it because I'm not using an initramfs?

This is x86_64 Gentoo Linux with kernel 3.10.7. I'm using a MBR partition table on sda and a GUID partition table on sdb.

cjm
  • 26,740
  • 12
  • 88
  • 84
  • `unknown-block(0,0)` looks like a GRUB device to me. my guess is that GRUB can't use that UUID for some reason. – strugee Oct 06 '13 at 04:29
  • @strugee, I don't think GRUB attempts to interpret the kernel command line at all. (GRUB is loading the kernel from `sda1`. I didn't show that part of the config.) – cjm Oct 06 '13 at 04:32
  • I'm inclined to agree. it's weird, though, that the device looks like a GRUB device instead of a UNIX device. – strugee Oct 06 '13 at 04:34
  • @Gilles, the question isn't about GRUB. That just happens to be the bootloader I'm using. It's a Linux kernel question. – cjm Oct 07 '13 at 19:31
  • This isn't a question about the kernel either - this is a question about `init`. – mikeserv Aug 21 '14 at 22:48
  • Why do you say you do not use an initramfs image? What then is `/bzImage`? Moreover *all* linux kernels have initramfs since 2.6 - it is *always* the first `/` mounted. You can either compile the image in *(which occurs anyway - it's just an essentially empty `/`)* or you can specify it on the kernel commandline. – mikeserv Aug 22 '14 at 07:27

3 Answers3

33

Just to clarify UUIDs are the only reliable way for the kernel to identify hard drives. There are two types: UUID, which is stored in the filesystem and is not available to the kernel at boot-time, and PARTUUID, which is stored in the partition table and IS available at boot time. So you have to use

root=PARTUUID=SSSSSSSS-PP

as /dev/sd?? can change with devices plugged/unplugged.

Don't forget to capitalize the hexadecimal number SSSSSSSS-PP you get from blkid!

The more easy to use

root=LABEL=
root=UUID=

only work with an initramfs that fetches these identifiers.

So, if you use a non-empty initramfs, you can have all three! With an empty initramfs, you only have PARTUUID.

ineiti
  • 451
  • 4
  • 5
  • Mind to explain who is using the boot=-argument then? I just used this line for an Archlinuxarm installation that doesn't have initrd, and where I can't use boot=LABEL nor boot=UUID. – ineiti Aug 21 '14 at 22:48
  • 1
    You're right - I corrected the boot to root, sorry! Hope it makes more sense now. – ineiti Aug 21 '14 at 22:57
  • Yes. The kernel will interpret a `root=` flag - but not in the sense i think you mean. There is no such thing as *without initramfs* - the `root=` flag *points* to an initramfs image which the kernel will extract into its own / with `cpio`. *initrd* is extinct - and has been since the 2.6 kernel was introduced. – mikeserv Aug 21 '14 at 23:01
  • 1
    My understanding (after one day on the forums of archlinuxarm) is that there is no initrd (or initramfs, but https://www.kernel.org/doc/Documentation/kernel-parameters.txt calls it initrd) on Archlinuxarm. On Ubuntu and such I do give a pointer to initrd, but (as to my understanding) not on Archlinuxarm. – ineiti Aug 22 '14 at 06:54
  • 1
    Archlinuxarm discussion about NO initrd: http://archlinuxarm.org/forum/viewtopic.php?f=23&t=6652 – ineiti Aug 22 '14 at 07:18
  • 1
    Try [this](https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt) link. And [this](http://unix.stackexchange.com/a/123517/52934) one. And maybe [this](http://unix.stackexchange.com/a/146037/52934) one. initramfs is *not* the initramfs image - which is usually a compressed archive containing a `cpio` archive that the kernel unpacks to `/` at boot. initramfs is a filesystem - it is always the first `/` mounted and from whence the kernel calls `init`. You can compile the contents into the kernel or unpack them at boot - those are the two options. – mikeserv Aug 22 '14 at 07:33
  • Thanks a lot, I appreciate the links. I just checked the config-file for the linux-kernel on Archlinuxarm, and `CONFIG_INITRAMFS_SOURCE=""`, so I think the initramfs is empty and the kernel will simply try to mount the filesystem given with `root=`, according to your first link, first paragraph of _What is initramfs?_. Then it will start `/sbin/init` from the root filesystem. Thanks for banging initrd and initramfs in my head ;) – ineiti Aug 22 '14 at 16:23
  • Capitalizing the PARTUUID hex numbers doesn't seem to be required at least as of kernel 5.10 for the Raspberry Pi. – genpfault Feb 28 '22 at 18:12
  • Based on this question https://unix.stackexchange.com/questions/655200 (which definitely repeatably happens, for me), I believe your suggestion to capitalize the UUID values is exactly wrong (boots, but significantly slows down boot, as compared to using the original lower case). – MikeBeaton Mar 03 '22 at 13:49
20

The parameter you have to pass to boot from UUID is PARTUUID. So it should be root=PARTUUID=666c2eee-193d-42db-a490-4c444342bd4e.

The documentation explains why it's coming back with unknown-block(0,0):

kernel-parameters.txt:

    root=       [KNL] Root filesystem
            See name_to_dev_t comment in init/do_mounts.c.

init/do_mounts.c:

/*
 *  Convert a name into device number.  We accept the following variants:
 *
 *  1) device number in hexadecimal represents itself
 *  2) /dev/nfs represents Root_NFS (0xff)
 *  3) /dev/<disk_name> represents the device number of disk
 *  4) /dev/<disk_name><decimal> represents the device number
 *         of partition - device number of disk plus the partition number
 *  5) /dev/<disk_name>p<decimal> - same as the above, that form is
 *     used when disk name of partitioned disk ends on a digit.
 *  6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
 *     unique id of a partition if the partition table provides it.
 *     The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
 *     partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
 *     filled hex representation of the 32-bit "NT disk signature", and PP
 *     is a zero-filled hex representation of the 1-based partition number.
 *  7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
 *     a partition with a known unique id.
 *
 *  If name doesn't have fall into the categories above, we return (0,0).
 *  block_class is used to check if something is a disk name. If the disk
 *  name contains slashes, the device name has them replaced with
 *  bangs.
 */

The last bit at the end says that if it can't understand the value, it returns (0,0), hence your error.

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
phemmer
  • 70,657
  • 19
  • 188
  • 223
  • 7
    So I guess that the real answer is that the kernel does not support `root=UUID`, only `root=PARTUUID`. If you want to use a filesystem UUID, I guess you need an initramfs that can handle mounting filesystems by UUID. – cjm Oct 06 '13 at 05:48
  • 1
    @cjm my `grub` boots quite happily with `root=UUID`. – terdon Oct 06 '13 at 14:30
  • 3
    @terdon, I'll bet you have an initramfs or initrd. (It could be linked into your kernel instead of being a separate file.) – cjm Oct 06 '13 at 14:59
  • 1
    Since 4.20, there's also support for PARTLABEL , which I think is really convenient. Perhaps update the answer. – equaeghe Jan 20 '21 at 11:13
  • `PARTLABEL=` only works for GPT partition tables (MBR doesn't support labels on partitions themselves). – Tom Hale Feb 23 '22 at 07:00
4

This is a 5 year old thread. But still it is imho not fully answered. There's a little example missing. Here it is:

In this example:

/dev/sda3 = /
/dev/sda2 = swap

...using a GPT partition. With MBR (dos partition) the PARTUUID's are shorter but the procedure is the same...

get the PARTUUID's with blkid:

blkid -s PARTUUID -o value /dev/sda3 # root
77fd7830-faa2-4e99-a48b-337ad9eded28
blkid -s PARTUUID -o value /dev/sda2 # swap
5b63167a-6fd2-4e72-948c-90832372956c

/boot/grub/grub.cfg:

search --no-floppy --part-uuid --set=root 77fd7830-faa2-4e99-a48b-337ad9eded28

menuentry "GNU/Linux, KERNEL 4.12.7-lfs-8.1" {
  linux /boot/vmlinuz-4.12.7-lfs-8.1 root=PARTUUID=77fd7830-faa2-4e99-a48b-337ad9eded28 net.ifnames=0 ipv6.disable=1 ro rootwait rootfstype=ext4
}

/etc/fstab/:

PARTUUID=77fd7830-faa2-4e99-a48b-337ad9eded28 / ext4 noatime,nodiratime,errors=remount-ro 0 1
PARTUUID=5b63167a-6fd2-4e72-948c-90832372956c swap swap pri=1 0 0

This is known to WORK with lfs8.1 (kernel 4.12.7) But i think it should work with most other kernels too (olders and newers...)