XFSからBtrfsへ移行

3 分で読める

メインのデスクトップPCのSSDをリプレースするついでに、ファイルシステムもXFSから新しくしようかなと思い、Btrfsへ移行した作業記録を残しておきます。

特にXFSに不満があったわけではないのですが(バグ踏み抜いてデータぶっ壊れたことはあったけど……)、スナップショットや透過圧縮も使いたいし、Fedora 33からデスクトップ向けはファイルシステムがBtrfsがデフォルトになったこともあり、移行を決意しました。

ディスク構成

XFSからBtrfsへはインプレースで変換できないので、別ディスクに作ってデータをコピーする流れです。 パーティションはテキトーに切っておくとして、手順は割愛します。

  • /dev/sda: 移行元
    • /dev/sda1: ESP
    • /dev/sda2: /boot
    • /dev/sda3: /
  • /dev/nvme0n1: 移行先
    • /dev/nvme0n1p1: ESP
    • /dev/nvme0n1p2: /

Fedora Liveイメージを書き込んだUSBメモリからブートして作業します。

フォーマット/サブボリューム作成

まずはBtrfsでフォーマットして、サブボリュームを作成していきます。

# mkfs.btrfs -f /dev/nvme0n1p2

ArchWikiのBtrfs#サブボリュームを参照すると、トップレベルのサブボリュームを/にマウントしないようにするなど、運用上の理由で推奨されるレイアウトがあるようです。

とりあえずSnapper推奨レイアウトっぽく作成しておきました。

# mount -t btrfs /dev/nvme0n1p2 /mnt
# cd /mnt
# btrfs sub create @
# btrfs sub create @home
# btrfs sub create @log
# btrfs sub create @snapshots
# btrfs sub list -p -a .
ID 256 gen 13 parent 5 top level 5 path <FS_TREE>/@
ID 257 gen 8 parent 5 top level 5 path <FS_TREE>/@log
ID 258 gen 9 parent 5 top level 5 path <FS_TREE>/@snapshots
ID 259 gen 10 parent 5 top level 5 path <FS_TREE>/@home

サブボリュームをマウントしていきます。Fedora 34からztsdによる透過圧縮がデフォルトで有効になるそうなので、透過圧縮していきましょう!

# umount /mnt
# mount -o defaults,noatime,ssd,compress=zstd:1,subvol=@ /dev/nvme0n1p2 /mnt
# mkdir home
# mount -o defaults,noatime,ssd,compress=zstd:1,subvol=@home /dev/nvme0n1p2 /mnt/home
# mkdir -p var/log
# mount -o defaults,noatime,ssd,compress=zstd:1,subvol=@log /dev/nvme0n1p2 /mnt/var/log
# mkdir boot/efi
# mount /dev/nvme0n1p1 /mnt/boot/efi
# findmnt
└─/mnt                        /dev/nvme0n1p2[/@]
                                         btrfs        rw,noatime,seclabel,compress=zstd:1,ssd,space_cache,subvolid=256,subvol=/@
  ├─/mnt/home                 /dev/nvme0n1p2[/@home]
  │                                      btrfs        rw,noatime,seclabel,compress=zstd:1,ssd,space_cache,subvolid=259,subvol=/@home
  └─/mnt/var/log              /dev/nvme0n1p2[/@log]
                                         btrfs        rw,noatime,seclabel,compress=zstd:1,ssd,space_cache,subvolid=257,subvol=/@log

データ移行

パーティションを確認。sda3がルートパーティションです。

# lsblk /dev/sda
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 931.5G  0 disk 
├─sda1   8:1    0   200M  0 part 
├─sda2   8:2    0     1G  0 part 
└─sda3   8:3    0 930.3G  0 part 

移行元のルートパーティションをマウントして、rsyncでまるっとコピーします。

# mkdir /old
# mount -t xfs -o ro /dev/sda3 /old
# rsync -aAHS --info=progress2 --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /old/ /mnt

fstabの設定

UUIDを確認して、

# blkid | grep nvme
/dev/nvme0n1p1: SEC_TYPE="msdos" UUID="3B15-A6E7" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="107b944b-5213-4888-96bf-0423ce5f4b32"
/dev/nvme0n1p2: UUID="579d5095-d274-4ecb-a66a-866ef9984aaf" UUID_SUB="178a8f45-1ab0-4fb4-8393-8c977b766670" BLOCK_SIZE="4096" TYPE="btrfs" PARTUUID="9e51d582-55c5-4116-864c-7ba14f94c474"

各サブボリュームのマウントを記述します。Btrfs固有のオプションについては、サブボリューム毎に別のオプションを設定できる訳ではないようです。 将来的にはできるようになるらしい (=> Can I mount subvolumes with different mount options?)

# vim /mnt/etc/fstab 
UUID=3B15-A6E7          /boot/efi               vfat    umask=0077,shortname=winnt 0 2
UUID=579d5095-d274-4ecb-a66a-866ef9984aaf	/	btrfs	rw,noatime,space_cache=v2,compress=zstd:1,subvol=/@	0 0
UUID=579d5095-d274-4ecb-a66a-866ef9984aaf	/home	btrfs	rw,noatime,space_cache=v2,compress=zstd:1,subvol=/@home	0 0
UUID=579d5095-d274-4ecb-a66a-866ef9984aaf	/var/log	btrfs	rw,noatime,space_cache=v2,compress=zstd:1,subvol=/@log	0 0

GRUBの設定

移行先のディスクで起動できるようにするために、GRUB周りの設定を移行先に合わせて初期化します。

面倒を起こさないように以下のオプションは無効化しておきます。

# vim /etc/default/grub
GRUB_DISABLE_OS_PROBER=true
GRUB_SAVEDEFAULT=false

移行先のディスクでchrootして、ブートに必要なお膳立てをしてあげます。色々方法はあるようですが、ざっくり再インストールしてやれば簡単です。

# mount --bind /dev /mnt/dev
# mount --bind /proc /mnt/proc
# mount --bind /sys /mnt/sys
# mount --bind /run /mnt/run
# chroot /mnt
# dnf reinstall grub2-efi grub2-tools shim
# dnf reinstall kernel*
(Fedora 33以前)
# grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
(Fedora 34)
# grub2-mkconfig -o /etc/grub2-efi.cfg

これで再起動して、無事ブートしてくれれば完了です。

comments powered by Disqus