SSD 上的 Btrfs,“设备上没有剩余空间”;使用“fstrim”和“btrfs balance”陷入困境;如何恢复?

SSD 上的 Btrfs,“设备上没有剩余空间”;使用“fstrim”和“btrfs balance”陷入困境;如何恢复?

我的 Kubuntu 的根文件系统(安装在 下/)是 Btrfs。我没有将其用作-o discard挂载选项。这意味着我需要fstrim按需运行

过去我遇到过这个问题:btrfs,没有剩余磁盘空间。我注意到fstrim -v /几乎没有空间被修剪。我的解决方案是btrfs balance start /在之前运行fstrim。这是要点我的答案在那里

今天情况不同了。也许我维护得太晚了。情况如下:

# fstrim -v /
/: 24 KiB (24576 bytes) trimmed
# btrfs balance start /
ERROR: error during balancing '/': No space left on device

我删除了一些子卷(快照),btrfs subvolume delete …但没用。我记不太清楚细节,但我认为以前我可以运行,btrfs balance …因为初步fstrim修剪了至少几个 MiB,而不是像今天这样少到 24 KiB。现在这似乎是一个两难的境地,只有当另一个先完成工作时,fstrim或才会起作用。btrfs balance

需要说明的是,以下统计数据表明我确实有足够的空间:

# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       112G   43G   68G  39% /

# btrfs fi df /
Data, single: total=108.73GiB, used=41.00GiB
System, single: total=64.00MiB, used=16.00KiB
Metadata, single: total=3.00GiB, used=1.02GiB
GlobalReserve, single: total=352.00MiB, used=0.00B

注意,在正常操作期间,我还没有遇到“设备上没有剩余空间”的情况。我认为 Btrfs 会不断将新写入内容放入已占用的块中。但是,过去我在 期间遇到“没有剩余空间……” apt-get upgrade,然后我使用 和 恢复btrfs balancefstrim我不知道什么时候(如果)这种情况会再次袭击我。我想在做重要的事情时在出现“没有剩余空间……”之前进行维护。

如何从这种情况中恢复过来fstrim并且btrfs balance不互相阻碍?我可以从正在运行的系统内部修复这个问题吗?

事实上我已经修复了这个问题,我的答案如下。这个问题是为了以后参考。欢迎添加其他解决方案。


附加信息:

$ uname -a
Linux foobar 4.4.0-78-generic #99-Ubuntu SMP […] x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/issue
Ubuntu 16.04.3 LTS \n \l

# dpkg -l | grep btrfs
ii  btrfs-tools  4.4-1ubuntu1  amd64  Checksumming Copy on Write Filesystem utilities

答案1

是的,您可以从正在运行的系统内恢复。我原来的方法如下;但是,多亏了 Zan Lynx 的评论,我找到了一种更简单的方法。

我的改进方法

这是提到的评论:

或者,如果你提前考虑,你可以告诉 btrfs 使用少于设备最大值的btrfs filesystem resize

(与我原来的方法相比,重点是故意在这个特定的设备上留出一些可用空间并在那里扩展文件系统,而不是添加一个单独的设备,这可能不那么容易。)

好消息:我的测试表明我不必提前考虑!即使btrfs balance start /抛出“没有剩余空间……”,我仍然能够缩小文件系统,只要有空间(即所有文件和元数据都适合新大小)。这导致以下解决方案:

# btrfs filesystem resize -100M /  # shrink a little...
Resize '/' of '-100M'
# btrfs filesystem resize +100M /  # ... and expand back
Resize '/' of '+100M'
# btrfs balance start /            # should work now
Done, had to relocate 88 out of 88 chunks
# fstrim -v /
/: 67,8 GiB (72753831936 bytes) trimmed

我原来的做法

这是您需要做的(详细描述如下):

  1. 向 Btrfs 文件系统添加额外的设备。
  2. btrfs balance start …
  3. fstrim …
  4. 从 Btrfs 文件系统中删除多余的设备。
  5. btrfs balance start …
  6. fstrim …

诀窍是向 Btrfs 文件系统添加一个额外的设备,这样就btrfs balance …可以有一些额外的空间。该设备可能类似于/dev/sdb/dev/sdb3。在此示例中,我使用 HDD 上的常规 1 GiB 文件(很重要:我仔细检查了文件是否不属于我想要扩展的 Btrfs 文件系统!这可能是致命的)。我认为 RAM 中的文件(例如/dev/shm/)应该也可以。

# tmpf=/mnt/hdd/tempfile   # if this file exists, it will be overwritten!
# truncate -s 1G "$tmpf"
# extra=$(losetup -f --show "$tmpf")

现在$extra就像/dev/loop0或什么的。

# btrfs device add "$extra" /

此时我不能重启我的操作系统。如果我重启,它将缺少其根文件系统的一部分,因为没有/dev/loop*与 关联/mnt/hdd/tempfile。如果您使用常规设备(或分区)作为额外设备,这将不是问题,因为btrfs device scan在启动过程中会检测到它。

# btrfs balance start /

在我的情况下,这tempfile是一个稀疏文件。在另一个控制台中,我运行watch ls -hls /mnt/hdd/tempfile并注意到它何时增长到(几乎)满大小。这样我就知道一些 Btrfs 块何时从 SSD 中移动。如果有任何疑问,请让btrfs ballance …finish; 但我会调用btrfs balance cancel /以节省一些时间。现在让我们回到主控制台。

注意:下面的第一行来自上面btrfs balance start /被中断的命令。

balance canceled by user
# fstrim -v /
/: 26,7 GiB (28696862720 bytes) trimmed

fstrim比以前修剪得更多。我不再需要额外的设备了。

# btrfs device delete "$extra" /   # may take a while
# btrfs balance start /            # should work now
Done, had to relocate 88 out of 88 chunks
# fstrim -v /
/: 67,8 GiB (72753831936 bytes) trimmed

就是这样。现在该清理了:

# losetup -d "$extra"
# rm "$tmpf"

相关内容