diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index f86ba6a319fe638cc5a56da6602d4418bbd66eaf..2f1ff7007280037d33da90e495cef7ed87be3e95 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1974,7 +1974,22 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio) cleanup_io: if (rbio->operation == BTRFS_RBIO_READ_REBUILD) { - if (err == BLK_STS_OK) + /* + * - In case of two failures, where rbio->failb != -1: + * + * Do not cache this rbio since the above read reconstruction + * (raid6_datap_recov() or raid6_2data_recov()) may have + * changed some content of stripes which are not identical to + * on-disk content any more, otherwise, a later write/recover + * may steal stripe_pages from this rbio and end up with + * corruptions or rebuild failures. + * + * - In case of single failure, where rbio->failb == -1: + * + * Cache this rbio iff the above read reconstruction is + * excuted without problems. + */ + if (err == BLK_STS_OK && rbio->failb < 0) cache_rbio_pages(rbio); else clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);