BTRFS 删除丢失的驱动器,忽略 I/O 错误

BTRFS 删除丢失的驱动器,忽略 I/O 错误

我有一个 BTRFS 文件系统,分布在 3 个驱动器上(无 RAID)。我的一个驱动器昨天坏了。我仍然可以使用以下方式挂载文件系统

sudo mount $path -o degraded,ro

大约 12 万个文件(共 110 万个)出现读取错误,其余文件仍然存在。我有备份,但如何从阵列中移除丢失的磁盘,而不破坏所有数据?

我试过

sudo btrfs device delete missing $path

,但输出为ERROR: error removing the device 'missing' - Read-only file system,但由于缺少驱动器,我无法以读/写方式安装它......

显而易见的解决方案是将所有工作数据复制到新的文件系统,但我目前没有另一个 4TB 驱动器,因此如果我可以只删除损坏的文件,然后从备份中恢复,那就太好了。

答案1

我遇到了同样的问题。我将一个新磁盘添加到 DATA:single、METADATA:raid1、SYSTEM:raid1 的多设备阵列中。大约 2 分钟后,新磁盘发生故障,留下以下信息:

tassadar@sunfyre:~$ sudo btrfs fi usage /mnt/store
Overall:
    Device size:                   7.28TiB
    Device allocated:              7.14TiB
    Device unallocated:          140.98GiB
    Device missing:                  0.00B
    Used:                          7.14TiB
    Free (estimated):            141.99GiB      (min: 71.50GiB)
    Data ratio:                       1.00
    Metadata ratio:                   2.00
    Global reserve:              512.00MiB      (used: 96.00KiB)

Data,single: Size:7.06TiB, Used:7.05TiB
   /dev/sdc1       3.53TiB
   /dev/sdd1       3.53TiB
   missing         2.00GiB

Metadata,RAID1: Size:43.00GiB, Used:41.81GiB
   /dev/sdc1      43.00GiB
   /dev/sdd1      43.00GiB

System,RAID1: Size:32.00MiB, Used:880.00KiB
   /dev/sdc1      32.00MiB
   /dev/sdd1      32.00MiB

Unallocated:
   /dev/sdc1      70.99GiB
   /dev/sdd1      69.99GiB
   missing         3.71TiB

它只能用 ro,degraded 挂载,当我需要移除丢失的设备时,这毫无用处。我找不到任何方法来修复这个问题,而且这些磁盘上的数据不是很重要,所以我开始在内核中捣鼓。

解决方法

以下所有内容显然都非常不安全,盲目复制粘贴所有内容可能不是最好的主意。

这些是我对 vanilla 4.7.4 内核树所做的更改,主要是“注释掉我不太理解的东西”的古老技巧(语法高亮):

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 864cf3b..bd10a1d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3588,6 +3588,8 @@ int btrfs_calc_num_tolerated_disk_barrier_failures(
        int num_tolerated_disk_barrier_failures =
                (int)fs_info->fs_devices->num_devices;

+       return num_tolerated_disk_barrier_failures;
+
        for (i = 0; i < ARRAY_SIZE(types); i++) {
                struct btrfs_space_info *tmp;

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 589f128..cbcb7b2 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2817,7 +2817,8 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
                }

                if (map->stripes[i].dev) {
-                       ret = btrfs_update_device(trans, map->stripes[i].dev);
+//                     ret = btrfs_update_device(trans, map->stripes[i].dev);
+                       ret = 0;
                        if (ret) {
                                mutex_unlock(&fs_devices->device_list_mutex);
                                btrfs_abort_transaction(trans, root, ret);
@@ -2878,13 +2879,15 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset)
         */
        ASSERT(mutex_is_locked(&root->fs_info->delete_unused_bgs_mutex));

-       ret = btrfs_can_relocate(extent_root, chunk_offset);
+//     ret = btrfs_can_relocate(extent_root, chunk_offset);
+       ret = 0;
        if (ret)
                return -ENOSPC;

        /* step one, relocate all the extents inside this chunk */
        btrfs_scrub_pause(root);
-       ret = btrfs_relocate_block_group(extent_root, chunk_offset);
+//     ret = btrfs_relocate_block_group(extent_root, chunk_offset);
+       ret = 0;
        btrfs_scrub_continue(root);
        if (ret)
                return ret;

基本上,它执行了整个“将扩展区移动到另一台设备”部分,而没有真正移动扩展区 -> 它只是删除了丢失驱动器上的旧扩展区。它还允许我以读写方式挂载 fs。将此“补丁”与(其他)健康的 btrfs 系统一起使用是不安全的。

设备删除现在“有效”:

tassadar@sunfyre:~$ sudo mount -o degraded /dev/sdd1 /mnt/store

tassadar@sunfyre:~$ sudo btrfs device delete missing /mnt/store
ERROR: error removing device 'missing': No such file or directory

tassadar@sunfyre:~$ sudo btrfs fi usage /mnt/store
Overall:
    Device size:                   7.28TiB
    Device allocated:              7.14TiB
    Device unallocated:          140.98GiB
    Device missing:                  0.00B
    Used:                          7.14TiB
    Free (estimated):            141.99GiB      (min: 71.50GiB)
    Data ratio:                       1.00
    Metadata ratio:                   2.00
    Global reserve:              512.00MiB      (used: 96.00KiB)

Data,single: Size:7.06TiB, Used:7.05TiB
   /dev/sdc1       3.53TiB
   /dev/sdd1       3.53TiB

Metadata,RAID1: Size:43.00GiB, Used:41.81GiB
   /dev/sdc1      43.00GiB
   /dev/sdd1      43.00GiB

System,RAID1: Size:32.00MiB, Used:880.00KiB
   /dev/sdc1      32.00MiB
   /dev/sdd1      32.00MiB

Unallocated:
   /dev/sdc1      70.99GiB
   /dev/sdd1      69.99GiB
   missing           0.00B

tassadar@sunfyre:~$ sudo umount /mnt/store

tassadar@sunfyre:~$ sudo mount /dev/sdd1 /mnt/store

tassadar@sunfyre:~$ sudo btrfs fi usage /mnt/store
Overall:
    Device size:                   7.28TiB
    Device allocated:              7.14TiB
    Device unallocated:          140.98GiB
    Device missing:                  0.00B
    Used:                          7.14TiB
    Free (estimated):            141.99GiB      (min: 71.50GiB)
    Data ratio:                       1.00
    Metadata ratio:                   2.00
    Global reserve:              512.00MiB      (used: 0.00B)

Data,single: Size:7.06TiB, Used:7.05TiB
   /dev/sdc1       3.53TiB
   /dev/sdd1       3.53TiB

Metadata,RAID1: Size:43.00GiB, Used:41.81GiB
   /dev/sdc1      43.00GiB
   /dev/sdd1      43.00GiB

System,RAID1: Size:32.00MiB, Used:880.00KiB
   /dev/sdc1      32.00MiB
   /dev/sdd1      32.00MiB

Unallocated:
   /dev/sdc1      70.99GiB
   /dev/sdd1      69.99GiB

确保尽快恢复到没有解决方法的原始内核。

结果

我的 fs 现在似乎没问题了。我可能丢失了故障磁盘上的少量数据,但当我以“单一”模式运行它时,这是意料之中的事。我目前正在运行 btrfs scrub 以查看是否有东西严重损坏,完成后会编辑此帖子。

编辑:擦洗过程顺利完成,但是fs 仍然损坏- 当我开始从中删除一些文件时,内核发现了一些文件位于丢失的驱动器上,并抛出了错误。因此,我再次修补了内核(这次是在干净的 4.7.4 之上,没有之前的更改):

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 82b912a..f10b3b6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6853,8 +6853,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,

                ret = update_block_group(trans, root, bytenr, num_bytes, 0);
                if (ret) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
-                       goto out;
+                       btrfs_err(info, "update_block group has failed (%d)", ret);
+                       ret = 0;
+                       //btrfs_abort_transaction(trans, extent_root, ret);
+                       //goto out;
                }
        }
        btrfs_release_path(path);

所以,这绝对不是一个好的解决方案,因为 FS 显然不行。但由于它现在可以使用,我并没有真正失去任何东西,而且这不是一个高优先级的存储,所以我很满意。

答案2

sudo mount -o degraded,ro /dev/sdd1 /media/btrfs

sudo btrfs de del missing /media/btrfs 错误:删除设备“丢失”时出错:只读文件系统

答案3

在使用 之前,必须先将降级的文件系统挂载为读写模式btrfs device delete missing。使用 挂载-o degraded应该可以正常工作。

相关内容