]> git.hungrycats.org Git - linux/commitdiff
btrfs: raid56: skip parking for sync rbios finished by their unplug batch
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 31 Jul 2026 08:41:19 +0000 (04:41 -0400)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 4 Sep 2026 17:16:57 +0000 (13:16 -0400)
Parking exists to widen the merge window, and for plugged submissions
the unplug callback is the natural end of that window from the
submitter's side: once raid_unplug() has sorted and merged the batch,
nothing more is coming from it.  A sync rbio parked after that point --
a sync(2) or WB_SYNC_ALL sweep, whose whole flush shares one plug --
has a waiter behind it and can only sit out the sync deadline.  Mark
rbios leaving an unplug batch and let sync ones skip parking.

Unplugged sync submissions (the fsync flush) still park: their sibling
bios arrive one by one and merge into the parked rbio, and the fsync
path kicks it as soon as they have all been submitted, so parking there
is the merge mechanism and the deadline already never fires.

Assisted-by: Claude:claude-fable-5
fs/btrfs/raid56.c

index ebefa58e926552abdb7018a8c7b271484c1ad606..5972f76281629e68df39bd0180546a3ee3d3f180 100644 (file)
  */
 #define RBIO_PADDED_BIT                5
 
+/*
+ * Set when an unplug callback finished merging this rbio's submission
+ * batch: the submitter has no more bios coming.  A sync rbio past this
+ * point gains nothing from parking (its own batch is fully merged and a
+ * waiter is behind it), so it skips straight to the write.
+ */
+#define RBIO_BATCH_DONE_BIT    6
+
 /* Set at park time and never cleared: this rbio once parked (stats). */
 #define RBIO_WAS_PARKED_BIT    7
 
@@ -799,6 +807,18 @@ static bool rbio_try_park(struct btrfs_raid_bio *rbio)
            timeout_ms == BTRFS_RBIO_PARK_SYNC_TIMEOUT_MS)
                return false;
 
+       /*
+        * A sync rbio whose submission batch was already merged by its
+        * unplug callback has nothing more coming from its submitter; the
+        * only thing parking can add is its deadline.  (Unplugged sync
+        * submissions -- the fsync flush -- still park: their sibling bios
+        * arrive one by one and merge into the parked rbio, and the fsync
+        * path kicks it as soon as they have all been submitted.)
+        */
+       if (test_bit(RBIO_BATCH_DONE_BIT, &rbio->flags) &&
+           timeout_ms == BTRFS_RBIO_PARK_SYNC_TIMEOUT_MS)
+               return false;
+
        spin_lock(&table->parked_lock);
        set_bit(RBIO_PARKED_BIT, &rbio->flags);
        set_bit(RBIO_WAS_PARKED_BIT, &rbio->flags);
@@ -1976,12 +1996,15 @@ static void raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
                                free_raid_bio(cur);
                                continue;
                        }
+                       set_bit(RBIO_BATCH_DONE_BIT, &last->flags);
                        start_async_work(last, rmw_rbio_work);
                }
                last = cur;
        }
-       if (last)
+       if (last) {
+               set_bit(RBIO_BATCH_DONE_BIT, &last->flags);
                start_async_work(last, rmw_rbio_work);
+       }
        kfree(plug);
 }