Raspbian上的btrfs根文件系统


11

我以为我可以尝试使用btrfs作为根分区,以了解它在断电期间如何处理文件损坏。但是我无法启动它。

我做了什么:

  1. 在切换之前在PI上:

    apt-get install btrfs-tools 2.在Linux计算机上:

    btrfs转换/ dev / sda2

  2. /etc/fstab变化ext4btrfs

  3. /cmdline.txt变化ext4btrfs

如果尝试启动,则会出现内核崩溃。我还应该做其他事情吗?

Answers:


7

如果btrfs被编译为内核模块,则需要创建一个initramfs来在引导时加载该模块。在Raspian(和其他debian衍生产品)上,update-initramfs是执行此操作的最简单方法。

如果initramfs-tools已安装,则任何时候apt-get安装新内核,它都会update-initramfs自动触发。

sudo apt-get update
sudo apt-get install initramfs-tools

但是,如果您用于rpi-update安装新内核,则需要update-initramfs在重新引导到新内核之前手动运行:

sudo update-initramfs -u -k <kernel-version>

这将在中创建或更新initramfs /boot/initrd.img-<kernel-version>

最后一步是将其添加到您的启动配置中:将以下行添加到/boot/config.txt

initramfs initrd.img-<kernel-version> followkernel

initrd-<kernel-version>必须与中的文件名完全匹配/boot

每次运行时,您都需要重复这些步骤rpi-update


2

我的快速测试表明,对btrfs的支持是作为raspbian中的外部模块构建的,而不是直接链接到内核中。

这意味着内核必须能够加载该模块(存储在根文件系统中),然后才能知道如何挂载根文件系统。显然,这是行不通的。

方法1:

构建自己的内核,并调整其构建配置以预链接btrfs。如果您已经了解了如何构建和加载自己的内核,则对配置进行调整很容易。

方法二:

重新调整内容,使内核和模块位于ext4文件系统上,而您最想压缩的数据位于btrfs分区上。

方法2A:

将根分区保留为ext4并创建一个基于btrfs的新分区,但这无助于减少OS的安装(如果这是您的目标)。

方法2B:

创建一个很小的引导分区,其中包含内核和模块,而其他所有内容都保留在btrfs上。我不知道如何为Pi的引导加载程序执行此操作,或者对此有什么限制。


怎样将btrfs模块复制到启动分区并事先从那里加载呢?
GuySoft

3
也不能从initrd.img开始吗?
Anders

是的,initrd.img看起来是解决它的最简单方法!我只是从未使用过。在“ mkinitrd”上查找文档。
DonGar

嗯,好像最新的Raspbian中未启用CONFIG_BLK_DEV_INITRD。这意味着您需要重新编译内核才能启用initd支持。
GuySoft

1
参见paxswill.com/blog/2013/11/04/encrypted-raspberry-pi-使用initramfs允许加密的根。同样,在root可用之前,需要对cryptsetup(此处为btrfs)的支持。
Rbjz 2014年

1

为了找到它的外部BTRFS根分区,我需要在引导分区的中明确指定根分区的UUIDcmdline.txt。例如:

dwc_otg.lpm_enable = 0 console = tty1 root = PARTUUID = 123e4567-e89b-12d3-a456-426655440000 rootfstype = btrfs电梯=截止日期rootwait安静启动

您可以使用确定BTRFS分区的UUID lsblk -f


1

btrfs默认情况下,Raspbian内核不支持该功能。最初的引导阶段正常运行,但是当内核加​​载时,它将看不到任何可以挂载的文件系统和混乱情况。存在解决方案:在initramfs中将btrfs添加为内核模块。在很大程度上要感谢三篇 不同的 文章,因此我将其设置为:

  • 安装所需的软件包-内核模块,以及使用它来更新initramfs的工具: sudo apt install btrfs-tools initramfs-tools
  • 告诉initramfs加载btrfs模块(出于某种原因应该自动发生,因为我的RPi1不能正常工作)-将“ btrfs”行添加到所需模块列表中: echo 'btrfs' | sudo tee -a /etc/initramfs-tools/modules
  • 为btrfs创建一个initramfs钩子(用于构建映像)和脚本(用于引导)-提供了默认值,但是在我的测试中,并没有自动使用它们,必须将它们复制到/ etc中。 sudo mkdir -p /etc/initramfs-tools/hooks ; sudo mkdir -p /etc/initramfs-tools/scripts/local-premount ; sudo cp /usr/share/initramfs-tools/hooks/btrfs /etc/initramfs-tools/hooks ; sudo cp /usr/share/initramfs-tools/scripts/local-premount/btrfs /etc/initramfs-tools/scripts/local-premount; sudo chmod +x /etc/initramfs-tools/hooks/btrfs /etc/initramfs-tools/scripts/local-premount/btrfs
  • -c为当前内核版本(uname -r)创建()新的initramfs-如果要更新现有的initramfs,则需要使用update(-u)。这将创建一个名为/boot/initrd.img-*的文件,其中*是当前内核版本。注意生成的名称(脚本将输出它),我们将在下一步中使用它。update-initramfs -c -k $(uname -r)
  • 编辑/boot/config.txt以使用此initramfs,并添加initramfs initrd.img-3.11.0+ followkernel文件名没有路径,它是上一步中生成的文件名;“ followkernel”控制内存中的位置(config.txt文档)。
  • 这就解决了当前的内核,但是正如@Ingo指出的那样,升级内核会破坏系统。为了解决这个问题,我使用了他的内核安装挂钩脚本

    • 编辑/ etc / default / raspberrypi-kernel并取消注释 INITRD=Yes
    • 删除 /etc/kernel/postinst.d/initramfs-tools
    • rpi-initramfs-tools添加到/etc/kernel/postinst.d/,chmod +x然后
    • (可选)下载update-rpi-initramfs,以更简便地手动更新initramfs。
  • 至此,我们有了一个可以使用btrfs作为根设备的系统。通过重新引导进行测试:系统仍将从ext4分区(或/boot/cmdline.txt中的任何内容引导,但dmesg | grep -i btrfs现在应显示包含“ Btrfs loading ”的行。现在,我们需要实际制作和使用btrfs分区。

  • 备份/(ext4)分区-假设它是/ dev / mmcblk0p2-通常:关闭RPi,取出SD卡,将其安装在其他位置(在此示例sudo mount /dev/mmcblk0p2 /mnt中为Linux计算机),然后将内容归档;请注意,您需要使用保留所有权和权限的工具,例如tar :(cd /mnt; sudo tar -czvf ~/rpi-rootfs-backup.tgz *然后再次卸载SD卡)

  • 在某个地方创建一个btrfs分区-我已经重新使用了SD卡,替换了ext4分区(/ dev / mmcblk0p2);如果您要创建一个btrfs-raid数组,这是这样做的时候了(这是mkfs.btrfs的参数之一,超出了此答案的范围):mkfs.btrfs /dev/mmcblk0p2
  • 挂载btrfs分区并将备份还原到其中: sudo partprobe; sudo mount /dev/mmcblk0p2 /mnt; cd /mnt; tar -xzvf ~/rpi-rootfs-backup.tgz
  • 在btrfs分区上编辑fstab :sudo nano /mnt/etc/fstab

应该有类似这样的行:

/dev/mmcblk0p2  / ext4 foo,bar,baz 0 1

将其更改为此(新的FS类型为btrfs,并使用默认选项):

/dev/mmcblk0p2  / btrfs defaults 0 1
  • 卸载分区,但不要删除SD卡! sudo umount /mnt
  • 我们需要告诉RPi它将从btrfs启动
  • 找到新btrfs分区的UUID-用/ dev / mmcblk0p2查找行,然后复制UUID =部分,并使用(不是UUID_SUB,不是PARTUUID!这会在引导加载程序中触发错误,并且内核也不会引导):sudo blkid

    / dev / mmcblk0p2:UUID =“ cafebeef-0000-1234-aaaa-12346589” UUID_SUB =“ ababccdd-2345-cafe-beee-587989991110” TYPE =“ btrfs” PARTUUID =“ beef0bee-02”

  • 挂载启动(FAT32)分区: sudo mount /dev/mmcblk0p1 /mnt

  • 编辑cmdline.txt: sudo nano /mnt/cmdline.txt

找到这两个参数

 root=PARTUUID=1234-5678 rootfstype=ext4

并替换为

 root=UUID=cafebeef-0000-1234-aaaa-12346589 rootfstype=btrfs

请注意,UUID是我们之前复制的UUID,只是没有引号。

  • 卸载RPi引导分区: sudo umount /mnt
  • 将SD卡插入RPi,然后启动。
  • 在RPi上,请查看您确实是从btrfs根挂载运行: mount

    / dev / mmcblk0p2 on /输入btrfs(rw,space_cache,subvol = /)

  • 等等!不完全是点击,而是通过站在巨人的肩膀上,我可以使它起作用。(也将其放入回购中。)


1
对于第一个(sudo apt upgrade如果它也可以升级)内核,此设置将在引导时严重失败,因为新内核尝试加载将失败的旧initramfs,并且内核无法加载btrfs驱动程序。而且,至少chroot在armhf系统上,这不是固定的简便方法。
Ingo,

升级内核时不会调用update-initramfs吗?
Piskvor在

1
不,默认情况下,Raspbian无法生成新的initramfs。尚未为此配置。apt upgrade在引导新内核之前,您始终必须用眼睛监视正在执行的操作,并在需要时手动生成initramfs。对于初学者而言,这不是一项可行的任务,因为失败会导致戏剧性的变化。您可以看看如何在启动Raspberry Pi时使用初始化ramdisk(initramfs)?
Ingo,

1
它有一个我刚刚发现的小错误,但到目前为止尚未修复。内核支持两个模型,例如4.14.98+4.14.98-v7+。如果update-initramfs由内核更新触发,它将生成两个initrd.img *,每个模型一个。这不适用于/boot分区(错误-空间不足),并且生成无法完成。
Ingo,

1
我考虑使用MODULES=list
Ingo,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.