Raspberry Pi 4 Model B で USB ブート(3) LVM 編

「[Raspberry Pi 4 Model B で USB ブート(2) パーティション作成編](https://qiita.com/nowlinuxing/items/7af17f1272ca0c558d47)」では USB マスストレージに基本パーティションを作成し、ext4 でフォーマットをして Raspberry Pi OS をそのままコピーした。
ところで、よくある x86 用の Linux ディストリビューションではインストール時に LVM を選択できる。Raspberry Pi 4 でも LVM を利用することは可能だ。
root パーティションで LVM を使うこともできる。ただし起動には initramfs を使う必要がある。

なお、前回までは（特に明記はしていなかったけれど）USB マスストレージへのインストールを PC で行っていたが、この方法だと initramfs を作成できないため、今回は microSD にインストールした Raspberry Pi OS から作業する。
これに伴い対象となるデバイスが `/dev/sdb` から `dev/sda` になるので注意。

## LVM 作成

パーティションを作成するところは前回と同じ。

```sh
$ sudo gdisk -l /dev/sda
GPT fdisk (gdisk) version 1.0.3

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
:
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          526335   256.0 MiB   0700
   2          526336      5860533134   2.7 TiB     8300
```

2 つめのパーティションに LVM を作成する。
名前は `pi-vg` とするが、他の名前にしてもいい。

```sh
# LVM 物理ボリュームを作成
$ sudo pvcreate /dev/sda2

# ボリュームグループ pi-vg を作成
$ sudo vgcreate pi-vg /dev/sda2

# 論理ボリュームを作成
# 今回使用した USB マスストレージの容量は 3TB。
# swap に 8GB 割り当てることを想定し、/ の容量は総容量から逆算している
$ sudo lvcreate --size 2786G --name root pi-vg
$ sudo lvcreate -l 100%FREE --name swap pi-vg

# 現時点のHDDの状態を確認
$ lsblk /dev/sda
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  2.7T  0 disk 
├─sda1            8:1    0  256M  0 part 
└─sda2            8:2    0  2.7T  0 part 
  ├─pi--vg-root 254:0    0  2.7T  0 lvm  
  └─pi--vg-swap 254:1    0  8.3G  0 lvm  
```

使用した USB マスストレージは HDD であり、データーの書き込みによるデバイスの劣化を心配する必要はないため、swap パーティションを作成した。
swap のサイズを決めるにあたっては以下の情報を参考にし、メモリとほぼ同じ容量を確保した。

* [第15章 swap領域 Red Hat Enterprise Linux 7 | Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-swapspace)

作成した boot, root, swap をフォーマットする。

```sh
$ sudo mkfs -t vfat /dev/sda1
$ sudo mkfs -t ext4 /dev/pi-vg/root
$ sudo mkswap       /dev/pi-vg/swap
```

## システムファイルのコピー

* microSD にインストールイメージをコピーしておく
* 起動した Raspberry Pi OS 上でインストールイメージをダウンロードする

などをすれば前回までと同じ方法でコピーができるが、ここではこの手間を省き、起動に使用した microSD からコピーをすることにする。

```sh
$ mkdir /tmp/root
$ sudo mount /dev/pi-vg/root /tmp/root/

# 実ファイルシステムではない devtmpfs, sysfs, proc, tmpfs, boot と
# ext4 フォーマット時に作成される lost+found 以外のディレクトリをコピー
$ cd /
$ sudo cp -a bin etc home lib media mnt opt root sbin srv tmp usr var /tmp/root/
$ cd /tmp/root/
$ sudo mkdir dev sys proc run boot tmp

# 後述の initramfs を作成するために、boot パーティションは /tmp/root 以下にマウントする
$ sudo mount /dev/sda1 /tmp/root/boot/
$ sudo cp -a /boot/* /tmp/root/boot/
```

## 起動設定の変更

`cmdline.txt`、`fstab` を更新する。
パーティション情報だけでなく、initramfs に関するオプションも指定する。

```sh
# root= に /dev/pi-vg/root を指定
# initramfs を使用するために initrd=0x01f00000 を追加する
# 起動に失敗する場合は quiet を削除すると、起動中のメッセージが画面に表示されるので原因を特定しやすくなる
# デバッグには break オプションも有用。詳しくは initramfs-tools(7) を参照
$ cat /tmp/root/boot/cmdline.txt
console=serial0,115200 console=tty1 root=/dev/pi-vg/root initrd=0x01f00000 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles

# 前回までと同じく、boot パーティションの PARTUUID を blkid コマンドで調べ指定
# SSD の場合はデバイスの劣化を防ぐために、/dev/pi-vg/root の defaults には "defaults,noatime" を指定する
$ cat /tmp/root/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=09468d30-111e-4028-8f37-16f65e497c25  /boot           vfat    defaults          0       2
/dev/pi-vg/root  /               ext4    defaults  0       1
/dev/pi-vg/swap  none            swap    sw  0       0
```

## initramfs

boot パーティションに `initrd.gz` を作成し、起動時にこれを使うようにする。

```sh
# /tmp/root 以下でコマンドを実行できるよう、各種ディレクトリを /tmp/root 以下にマウント
$ sudo mount --bind /sys  /tmp/root/sys
$ sudo mount --bind /proc /tmp/root/proc
$ sudo mount --bind /dev  /tmp/root/dev

# /tmp/root/boot に initrd.gz を作成
$ sudo chroot /tmp/root/ apt install lvm2
$ sudo chroot /tmp/root/ mkinitramfs -o /boot/initrd.gz

# boot/config.txt に "initramfs initrd.img followkernel" を追加
$ cat /tmp/root/boot/config.txt
:
initramfs initrd.gz 0x01f00000
```

冒頭で、PC で作業をすると initramfs を作成できない旨を書いたが、それはここでの `apt install lvm2` がうまく行かないため。
lvm2 パッケージのインストール後に initramfs を作成する処理が走るが、このときに正しいカーネルのバージョンが取得できないのが原因と思われる（詳細は追っていないので要確認）。

```sh
## 後始末
$ sudo umount /tmp/root/sys /tmp/root/proc /tmp/root/dev
$ sudo umount /tmp/root/boot
$ sudo umount /tmp/root
```

これでインストールは完了。
Raspberry Pi OS をシャットダウンし、microSD を抜き取ってから電源を入れれば USB マスストレージから起動できる。

## おまけ

手順が多くなってきたので、インストーラーを作ってみた。

https://github.com/nowlinuxing/rpi4-installer

---

* [Raspberry Pi 4 Model B で USB ブート(1)](https://qiita.com/nowlinuxing/items/3c7f61bca6e5ef0d1c47)
* [Raspberry Pi 4 Model B で USB ブート(2) パーティション作成編](https://qiita.com/nowlinuxing/items/7af17f1272ca0c558d47)
* [Raspberry Pi 4 Model B で USB ブート(3) LVM 編](https://qiita.com/nowlinuxing/items/b57b3aa910fee9b82052)