イマドキのディスクマウント方法

あなたの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パーティションテーブル[^tautology]を使っている場合はパーティションにラベルを設定できます。
`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パーティションテーブル[^tautology]を使っている場合はパーティションに設定された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`などを使った設定も可能ですが、堅牢性の観点から推奨されていません。[^udev-symlink]

# カーネル起動オプション(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?][link1]）
[link1]:http://unix.stackexchange.com/questions/93767/why-cant-i-specify-my-root-fs-with-a-uuid
注）PARTUUIDが使えるのはLinux-2.6.37以降です[^impl-partuuid]。それ以前はおとなしくUUIDとinitrdを組みあわせて使うしかありませんでした。

# 参考
- [永続的なブロックデバイスの命名 - ArchWiki](https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&cad=rja&uact=8&ved=0CCwQFjACahUKEwjwwdiz3ovIAhXHH6YKHeQhDKE&url=https%3A%2F%2Fwiki.archlinuxjp.org%2Findex.php%2F%25E6%25B0%25B8%25E7%25B6%259A%25E7%259A%2584%25E3%2581%25AA%25E3%2583%2596%25E3%2583%25AD%25E3%2583%2583%25E3%2582%25AF%25E3%2583%2587%25E3%2583%2590%25E3%2582%25A4%25E3%2582%25B9%25E3%2581%25AE%25E5%2591%25BD%25E5%2590%258D&usg=AFQjCNGdutG_d_hN0M1Ftn8bqiKbjqP-Og&sig2=2BKg0zAln2D6j1JvmXOZXw)

- 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) <hex_major><hex_minor> device number in hexadecimal represents itself
> *         no leading 0x, for example b302.
> *	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.
> *	8) <major>:<minor> 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.
> */

[^tautology]: 重言ですがご理解ください
[^udev-symlink]: mountコマンドのmanページ参照
[^impl-partuuid]: コミット番号: [b5af921ec02333e943efb59aca4f56b78fc0e100](https://github.com/torvalds/linux/commit/b5af921ec02333e943efb59aca4f56b78fc0e100)

# この記事を書いた動機
USBメモリーとかに`/`が入っているときには、カーネルの起動オプションに`rootdelay=n`とか`rootwait`と指定してデバイスを認識するまで待たなくてはいけないんですね…
これを知らなくて、VirtualBox上ではうまくブートできるのに実機だとうまく行かない！なんで！！！
結局、問題の解決に3日間かかったので、今むしゃくしゃして書いています。
このむしゃくしゃエネルギーが誰かの役に立てば幸いです。