Linux, 工作, 生活, 家人

Embedded, Linux

embedded system btrfs

這一篇是 btrfs 用在 embedded system 的開發測試上會用到的指令.

mkfs.btrfs /dev/sda2
這有一點要注意, 有些 btrfs tool 預設 sectorsize 是 4096, 但是新的系統不能再用 4096 了. 要用 65536 . 所以要改用

$ mkfs.btrfs -s 65536 /dev/sda2

首先 btrfs 的 tag 是樹狀的, 最頂端的 tag 應該是 root level “0”.
往下一層就是 level 5 , 所以一開始就要 mount 上去然後開 top level 5 的目錄. ex:

$ mount /dev/sda2 /mnt/disk
$ cd /mnt/disk
$ btrfs subvolume create @
$ btrfs subvolume create @home

這樣就會有二個預設的 top level 5 的目錄, 先 umount 再 mount 新的 tag 過的 partition. install 系統, ex:

$ umount /mnt/disk
$ mount -o subvol=@ /mnt/disk
$ mkdir -p /mnt/disk/home
$ mount -o subvol=@home /mnt/disk 
.... install linux into /mnt/disk 
# 在開機時直接 mount @home 到 /home , 這樣以後切換系統時就可以一直用 @home tag
$ echo "/dev/sda2 /home  btrfs  defaults,subvol=@home 0 0" >> /etc/fstab

做完之後, 就要做一個 snapshot, 以後就在 snapshot 上做事情, 弄壞了砍掉再重來就可以.

(假設系統都還沒有 mount)
$ mount /dev/sda2 /mnt/disk
$ cd /mnt/disk
$ btrfs subvolume snapshot @ 1604

這樣就會產生一個 1604 的 snapshot. 內容和 @ 內是一模一樣的

接下來不管在 這個 snapshot 如何惡搞也不會影響到 @ 的內容

開機參數, 如何在開機時選擇那一個 subvol 開機, 如果是 embedded system 用 u-boot, 寫在 bootarg 內就可以了. 參數是 rootflags=subvol=
ex: 在 uboot 下

$ setenv subvol 1604
$ setenv bootdev /dev/sda2
$ setenv updkrnargs=setenv bootargs  console=ttyAMA0,115200n8 earlycon=pl011,0x87e028000000 debug maxcpus=24 rootw
ait rw  rootflags=subvol=${subvol} root=${bootdev} coherent_pool=16M/
$ setenv start 'setenv ethact vnic3 ; dhcp ; run updkrnargs;  tftpboot $kernel_addr Image ; booti $kernel_addr - $fdtcontroladdr'

因為 u-boot 只能在 setenv 更新參數, 所以要再多一層 setenv 讀入參數.
這樣開機時, 就可以隨興設定 subvol, 開到正確的 subvol 上. 如果以後要砍掉, 砍掉這個 subvol 後再重建一個 snapshot. 省掉不少重灌的時間, 是不是很方便呢?

砍掉 subvol,
假設開到 @ 上去.

$ mount /dev/sda2 /mnt/disk
$ cd /mnt/disk
$ btrfs subvol del 1604
$ btrfs subvol snapshot @ 1604

有時候開發到一半想要留個備份, 也可以 snapshot, 就像 git tag 一版

$ mount -o subvol=1604 /dev/sda2 /mnt/disk
$ btrfs subvol snapshot /mnt/disk /mnt/disk/1604-backup

這樣就可以了, 接下去再怎麼亂搞也沒有關係, 都可以回到 1604-backup
如果是開到 1604 時, 會看到 1604-backup 在根目錄, 也可以直接刪除

# btrfs subvol del 1604-backup
Delete subvolume (no-commit): '//1604-backup'

是不是超方便的? 超像有 git 功能的 file system.
提外話: Microsoft 搞了一個 git 專用的 file systemfile system Announcing GVFS (Git Virtual File System)

如果系統是一般的 ubuntu, 沒有 u-boot, 想要改 grub 達到類似切換的效果. 個人的做法是在 @ 目錄下放一個檔案, 只要修改這個檔案之後, 就可以切換 subvol.

編輯 /etc/grub.d/10_linux, 找到 rootsubvol= 的字串, 改成圖內這樣

case x"$GRUB_FS" in
    xbtrfs)
        rootsubvol="`cat /root/defaultsubvol`" => 改成這樣, update 之後就可以切來切去了
        rootsubvol="${rootsubvol#/}"
        if [ "x${rootsubvol}" != x ]; then
            GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
        fi;;

以後就可以靠修改 @ 的 /root/defaultsubvol 然後再 update grub 達到切換不同 subvol 的目的.
ex:

$ mount -o subvol=@ /dev/sda2 /mnt/disk
$ for i in dev dev/pts sys proc run; do sudo mount --bind /$i mnt/disk/$i; done
$ chroot /mnt/disk
$ echo "1604-backup" > /root/defaultsubvol
$ update-grub

reboot 就會切換到 1604-backup

如果是己經開到 1604 下, 然後這時候針對 1604 的 root 用了 snapshot , 如果再開機的時候, subvol 就要加上上一層的名稱
像是這案例就要下 1604/odp
ex:

$ btrfs subvol snapshot / /odp
reboot to subvol 1604/odp
$ btrfs subvol list / 
ID 257 gen 446 top level 5 path @
ID 258 gen 1809 top level 5 path @home
ID 262 gen 1812 top level 5 path 1604
ID 268 gen 1807 top level 5 path gentoo
ID 276 gen 1689 top level 268 path gentoo/gentoo-1
ID 277 gen 1810 top level 262 path 1604/odp

這也不難理解, odp 是從 1604 snapshot 出來的放在 1604 下, 所以開到 1604 下會有一個 odp 的目錄, 就是指向 odp 的 snapshot.
簡單的說, 產生了一個新的目錄是 1604 根目錄的 snapshot.
如果不想要多一個 1604 , 可以 mount root 針對 1604 snapshot , 檔案放到 root 下即可.

可能剛開始會不習慣, 不過用了幾次之後就會發現這非常的省時間.
非常適合 embedded 開發用.

另外我不知道是不是我常常惡搞, 我的確有碰過一次整個 btrfs filesystem 壞掉. 雖然如此, 不影響它對我的方便性.

ref.
ArchLinux Btrfs

發佈留言