From: Zygo Blaxell Date: Fri, 31 Jul 2026 05:08:44 +0000 (-0400) Subject: btrfs: raid56: do not park sync writes into nocow runs X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f59ef5f2f0bc8c2ec6bd3ea22f7b89f8a7d17189;p=linux btrfs: raid56: do not park sync writes into nocow runs An in-place overwrite of a nodatacow file under stripe_alloc parked like any partial write, but with a waiter behind it and nothing worth merging: in-place overwrites arrive one fsync at a time, and unlike the datacow fsync path nothing kicks the parked rbio before the page writeback wait, so every fsync ate the full sync park deadline. Measured against stock nodatacow on the same rig, that deadline was the bulk of a ~3.7ms per-fsync regression. Skip parking for sync writes whose stripe belongs to a NOCOW-class run; async writeback still parks and merges there. Assisted-by: Claude:claude-fable-5 --- diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 6f3a7d2db8c49..9f01a4d5eccd4 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -770,8 +770,11 @@ static bool rbio_try_park(struct btrfs_raid_bio *rbio) struct btrfs_fs_info *fs_info = rbio->bioc->fs_info; struct btrfs_stripe_hash_table *table = fs_info->stripe_hash_table; unsigned int timeout_ms = BTRFS_RBIO_PARK_TIMEOUT_MS; + enum btrfs_stripe_run_class class; - if (!btrfs_stripe_in_open_run(fs_info, rbio->bioc->full_stripe_logical)) + if (!btrfs_stripe_open_run_class(fs_info, + rbio->bioc->full_stripe_logical, + &class)) return false; spin_lock(&rbio->bio_list_lock); @@ -779,6 +782,17 @@ static bool rbio_try_park(struct btrfs_raid_bio *rbio) timeout_ms = BTRFS_RBIO_PARK_SYNC_TIMEOUT_MS; spin_unlock(&rbio->bio_list_lock); + /* + * A sync write into a nodatacow inode's private run has a waiter + * behind it and nothing worth waiting to merge with: in-place + * overwrites arrive one fsync at a time, and the plain (unparked) + * write path is what stock nodatacow latency looks like. Park only + * async writeback there. + */ + if (class == BTRFS_STRIPE_RUN_NOCOW && + timeout_ms == BTRFS_RBIO_PARK_SYNC_TIMEOUT_MS) + return false; + spin_lock(&table->parked_lock); set_bit(RBIO_PARKED_BIT, &rbio->flags); rbio->park_deadline = jiffies + msecs_to_jiffies(timeout_ms);