SSD 上的 Btrfs,「裝置上沒有剩餘空間」; catch-22 與 `fstrim` 和 `btrfs Balance`;如何恢復?

SSD 上的 Btrfs,「裝置上沒有剩餘空間」; catch-22 與 `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。現在看來,這似乎是一個第 22 條軍規的情況,只有當另一個先完成其工作時,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 balance和恢復了fstrim。我不知道什麼時候(如果)這再次讓我震驚。當我做一些重要的事情時,我想在「沒有剩餘空間…」之前進行維護。

如何從這種情況中恢復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並注意到它何時增長到(幾乎)完整大小。這樣我就知道何時從 SSD 移動了一些 Btrfs 區塊。如有任何疑問,請btrfs ballance …完成;但我調用是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"

相關內容