Eu encontrei o mesmo problema. Eu adicionei um novo disco em uma matriz de vários dispositivos que foi DATA: single, METADATA: raid1, SYSTEM: raid1. O novo disco falhou cerca de 2 minutos depois, deixando-me com isto:
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
Era apenas montável com ro, degradado, o que é inútil quando preciso remover o dispositivo ausente. Eu não encontrei nenhuma maneira de consertar isso e os dados nesses discos não eram muito importantes, então eu comecei a hacking no kernel.
Solução alternativa
Todos os itens abaixo são obviamente muito inseguros e copiar tudo às cegas pode não ser a melhor ideia.
Estas são as mudanças que eu fiz na vanilla 4.7.4, principalmente o antigo ofício de "comentar coisas que eu realmente não entendo" ( com realce de sintaxe ):
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;
Basicamente, ele faz a parte "mover extensões para outro dispositivo" sem realmente mover as extensões - > apenas apaga os antigos na unidade ausente. Também me permite montar o fs read-write. Usar este "patch" com outros sistemas btrfs saudáveis não é seguro.
A exclusão de dispositivos "funciona" agora:
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
Certifique-se de voltar ao kernel original sem a solução alternativa o mais rápido possível.
Resultado
Meu fs parece estar bem agora. Eu poderia ter perdido uma pequena quantidade de dados que estava no disco com falha, mas isso é esperado quando eu o executei no modo "único". No momento, estou executando o scrubs do btrfs para ver se algo está terrivelmente quebrado ou não, editei este post assim que terminar.
EDIT: O scrub terminou sem nenhum problema, mas o fs ainda está corrompido - quando eu comecei a deletar alguns arquivos dele, o kernel encontrou alguns arquivos que estavam na unidade ausente e jogou um erro. Então, eu atualizei o kernel mais uma vez (desta vez no topo do 4.7.4 limpo, sem as mudanças anteriores):
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);
Então, sim, definitivamente não é uma boa solução, já que o FS obviamente não está bem. Mas desde que agora é utilizável, eu realmente não perdi nada e isso não era um armazenamento de alta prioridade, estou bastante satisfeito.