あなたのfstab、いまだに/dev/sda1
とか書いてませんか?
デバイスを認識順に依存して識別していたのは今や昔。
LABELやUUIDを使って恐怖のVFS: unable to mount root fs
祭から抜け出しましょう。
古い情報や間違った情報が錯綜しているので、まとめてみました。
fstab(mountコマンド)編
いくつかありますが、よく使われるものだけ説明します。
カーネルのデバイス名を使った指定
おなじみ/dev/sda1
などと指定する方法です。忘れましょう。
LABELを使った指定
ファイルシステムに付けるラベルを指定する方法です。ラベルを付与できないファイルシステムも有ります。
lsblk -f
した時のLABEL欄の内容を指定します。
例) LABEL=SYSTEM / ext4 rw,relatime,discard,data=ordered 0 1
引用符でクオートしてはいけません。スペースを含む場合は
例) LABEL=Shashin\040Data /media/100\040GB\040(Storage) ext4 defaults,noatime,user 0 2
のようにスペースを\040
で置き換えて表現する必要があります。
UUIDを使った指定
ファイルシステムを新規作成した際に作られる、UUIDを用いた指定方法です。当たり前ですが初期化するとUUIDは変化します。なお、UUIDは 必ず小文字 で書いてください。
lsblk -f
した時のUUID欄を指定します。
例) UUID=0a3407de-014b-458b-b5c1-848e92a327a3 / ext4 rw,discard,data=ordered 0 1
PARTLABELを使った指定
GPTパーティションテーブル1を使っている場合はパーティションにラベルを設定できます。
blkid
した際のPARTLABEL
を見てください。
例) PARTLABEL=EFI\040SYSTEM\040PARTITION /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2
PARTUUIDを使った指定
GPTパーティションテーブル1を使っている場合はパーティションに設定されたUUIDを指定できます。 必ず小文字 で指定してください。
blkid
した際のPARTUUID
がそれです。
例) PARTUUID=7280201c-fc5d-40f2-a9b2-466611d3d49e /home btrfs rw,noatime,ssd,discard,compress=lzo 0 0
注意
- PARTLABELやPARTUUIDを使った設定では、カーネルやSystemdまわりでのトラブルやバグが報告されています。どうしてもうまくいかない場合は早々に見切りをつけて他の手段を使った方が良いかもしれません。
-
/dev/disk/by-uuid
や/dev/disk/by-label
などを使った設定も可能ですが、堅牢性の観点から推奨されていません。2
カーネル起動オプション(CONFIG_CMDLINE、各種ブートローダ)編
ブート時にroot=/dev/sda1
などと指定するアレです。
良く使う指定方法は一つだけです。小文字、大文字のどちらでも大丈夫ですので、PARTUUIDを指定してください。それ以外のLABEL、UUID、PARTLABELを使った指定はできません。
例) root=PARTUUID=7280201c-fc5d-40f2-a9b2-466611d3d49e
例) root=PARTUUID=7280201C-FC5D-40F2-A9B2-466611D3D49E
UUIDやLABELを指定してうまく行く場合もありますが、それはinitramfs/initrdがよしなにやってくれているからであって、カーネル自体にUUID/LABELを読み取る能力はありません。(一般に、この時点ではファイルシステム関連のコードがまだロードされていません。)
よく、root=UUID=0a3407de-014b-458b-b5c1-848e92a327a3
などと指定するように説明されていますが、無効です。(参考: Why can't I specify my root fs with a UUID?)
注)PARTUUIDが使えるのはLinux-2.6.37以降です3。それ以前はおとなしくUUIDとinitrdを組みあわせて使うしかありませんでした。
参考
-
mountコマンドのmanページ
The recommended setup is to use tags (e.g. LABEL=label) rather than /dev/disk/by-{label,uuid,partuuid,partlabel} udev symlinks in the /etc/fstab file. Tags are more readable, robust and portable. The mount(8) command internally uses udev symlinks, so the use of symlinks in /etc/fstab has no advantage over tags. For more details see libblkid(3).
-
Linuxカーネルソースコード内のコメント(init/do_mounts.c)
/*
* Convert a name into device number. We accept the following variants:
*
* 1) device number in hexadecimal represents itself
* no leading 0x, for example b302.
* 2) /dev/nfs represents Root_NFS (0xff)
* 3) /dev/ represents the device number of disk
* 4) /dev/ represents the device number
* of partition - device number of disk plus the partition number
* 5) /dev/p - 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=/PARTNROFF= to select a partition in relation to
* a partition with a known unique id.
* 8) : major and minor number of the device separated by
* a colon.
*
* 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.
*/
この記事を書いた動機
USBメモリーとかに/
が入っているときには、カーネルの起動オプションにrootdelay=n
とかrootwait
と指定してデバイスを認識するまで待たなくてはいけないんですね…
これを知らなくて、VirtualBox上ではうまくブートできるのに実機だとうまく行かない!なんで!!!
結局、問題の解決に3日間かかったので、今むしゃくしゃして書いています。
このむしゃくしゃエネルギーが誰かの役に立てば幸いです。