|
@@ -2025,9 +2025,16 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
|
|
|
bio->bi_iter.bi_size = 0;
|
|
|
map_length = length;
|
|
|
|
|
|
+ /*
|
|
|
+ * Avoid races with device replace and make sure our bbio has devices
|
|
|
+ * associated to its stripes that don't go away while we are doing the
|
|
|
+ * read repair operation.
|
|
|
+ */
|
|
|
+ btrfs_bio_counter_inc_blocked(fs_info);
|
|
|
ret = btrfs_map_block(fs_info, WRITE, logical,
|
|
|
&map_length, &bbio, mirror_num);
|
|
|
if (ret) {
|
|
|
+ btrfs_bio_counter_dec(fs_info);
|
|
|
bio_put(bio);
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -2037,6 +2044,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
|
|
|
dev = bbio->stripes[mirror_num-1].dev;
|
|
|
btrfs_put_bbio(bbio);
|
|
|
if (!dev || !dev->bdev || !dev->writeable) {
|
|
|
+ btrfs_bio_counter_dec(fs_info);
|
|
|
bio_put(bio);
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -2045,6 +2053,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
|
|
|
|
|
|
if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
|
|
|
/* try to remap that extent elsewhere? */
|
|
|
+ btrfs_bio_counter_dec(fs_info);
|
|
|
bio_put(bio);
|
|
|
btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
|
|
|
return -EIO;
|
|
@@ -2054,6 +2063,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
|
|
|
"read error corrected: ino %llu off %llu (dev %s sector %llu)",
|
|
|
btrfs_ino(inode), start,
|
|
|
rcu_str_deref(dev->name), sector);
|
|
|
+ btrfs_bio_counter_dec(fs_info);
|
|
|
bio_put(bio);
|
|
|
return 0;
|
|
|
}
|