我有一个 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
应该可以正常工作。