diff mbox series

[13/14] btrfs: avoid recording full stripe write into write-intent bitmaps

Message ID 441b7bd4a0966c9f1d7ef17dea7a2e875440a728.1658726692.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: introduce write-intent bitmaps for RAID56 | expand

Commit Message

Qu Wenruo July 25, 2022, 5:38 a.m. UTC
Full stripe write can happen in the following cases:

- Writing into a completely new stripe
  In this case, even if powerloss happened, we won't have any committed
  metadata referring the new full stripe.

  Thus we don't need to recover.

- Writing into a NODATACOW range
  In this case, although in theory we should recovery after power loss,
  but NODATACOW implies NODATASUM, thus we have no way to determine
  which data is correct.

  Thus we don't need to and can't recover either.

So just avoid recording full stripe write into write-intent bitmaps.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/raid56.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 0a0a2a1e96c3..37e5fd5df1f9 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -818,8 +818,13 @@  static void rbio_orig_end_io(struct btrfs_raid_bio *rbio, blk_status_t err)
 	if (rbio->generic_bio_cnt)
 		btrfs_bio_counter_sub(rbio->bioc->fs_info, rbio->generic_bio_cnt);
 
-	/* Clear the write-intent bitmap range for write operation. */
-	if (rbio->operation == BTRFS_RBIO_WRITE)
+	/*
+	 * Clear the write-intent bitmap range for write operation.
+	 * For full stripe write we didn't record it into write-intent thus no
+	 * need to clear the bits for full stripe write.
+	 */
+	if (rbio->operation == BTRFS_RBIO_WRITE &&
+	    rbio->bio_list_bytes < rbio->nr_data * BTRFS_STRIPE_LEN)
 		btrfs_write_intent_clear_dirty(rbio->bioc->fs_info,
 				       rbio->bioc->raid_map[0],
 				       rbio->nr_data * BTRFS_STRIPE_LEN);
@@ -1342,13 +1347,19 @@  static noinline void finish_rmw(struct btrfs_raid_bio *rbio)
 	atomic_set(&rbio->stripes_pending, bio_list_size(&bio_list));
 	BUG_ON(atomic_read(&rbio->stripes_pending) == 0);
 
-	/* Update the write intent bitmap before we start submitting bios. */
-	btrfs_write_intent_mark_dirty(bioc->fs_info, rbio->bioc->raid_map[0],
-				     rbio->nr_data * BTRFS_STRIPE_LEN, &event);
-	ret = btrfs_write_intent_writeback(bioc->fs_info, event);
+	/*
+	 * Update the write intent bitmap if it's a sub-stripe write,
+	 * before we start submitting bios.
+	 */
+	if (rbio->bio_list_bytes < rbio->nr_data * BTRFS_STRIPE_LEN) {
+		btrfs_write_intent_mark_dirty(bioc->fs_info,
+				rbio->bioc->raid_map[0],
+				rbio->nr_data * BTRFS_STRIPE_LEN, &event);
+		ret = btrfs_write_intent_writeback(bioc->fs_info, event);
+		if (ret < 0)
+			goto cleanup;
+	}
 
-	if (ret < 0)
-		goto cleanup;
 	while ((bio = bio_list_pop(&bio_list))) {
 		bio->bi_end_io = raid_write_end_io;