diff mbox series

[RFC] btrfs: save the physical address for append writes before updating bi_status

Message ID 1fdf92c9de7d496e7591e67624def3dfdbbe577e.1695614683.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series [RFC] btrfs: save the physical address for append writes before updating bi_status | expand

Commit Message

Qu Wenruo Sept. 25, 2023, 4:05 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 4f3b693a16b1..42f1f87f1872 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -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);
 }