@@ -407,6 +407,10 @@ static void btrfs_orig_write_end_io(struct bio *bio)
btrfs_log_dev_io_error(bio, stripe->dev);
}
+ /* TODO: Add proper error handling for a single failed mirror case. */
+ if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
+ stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
+
/*
* Only send an error to the higher layers if it is beyond the tolerance
* threshold.
@@ -416,9 +420,6 @@ static void btrfs_orig_write_end_io(struct bio *bio)
else
bio->bi_status = BLK_STS_OK;
- if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
- stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
-
btrfs_orig_bbio_end_io(bbio);
btrfs_put_bioc(bioc);
}
There is a possible bug in side btrfs_orig_wrte_end_io(), that if the last mirror itself failed to do the APPEND write, but other mirrors succeeded. In that case, we know the write itself still succeeded, thus we reset bio->bi_status to BLK_STS_OK. But the next step, which would record the physical address, is dependent on the newly updated bio->bi_status (BLK_STS_OK). This means even the last mirror write failed, we still update the physical address for that stripe. Unfortunately I don't have any better solution for now but only move the "stripe->physical" assignment before the bi_status update. The proper fix needs some work from RST/zoned mode to handle such cases. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/bio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)