aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
authorMark Brown <broonie@kernel.org>2026-05-29 12:22:41 +0100
committerMark Brown <broonie@kernel.org>2026-05-29 12:22:41 +0100
commiteb539c57644157c4f14abdc3b646f3ad2e6170e2 (patch)
tree80048a74f4ef0c180390901fedaffa8f6ed405dd /fs
parent4b06ae5789cd47333135a6ad54afc1f43935db41 (diff)
parent792ceec96b623d01bdf85d96c3fe52cd83e2f023 (diff)
downloadlinux-next-history-eb539c57644157c4f14abdc3b646f3ad2e6170e2.tar.gz
Merge branch 'next-fixes' of https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/disk-io.c7
-rw-r--r--fs/btrfs/extent-tree.c5
-rw-r--r--fs/btrfs/extent_io.c10
-rw-r--r--fs/btrfs/fs.h1
-rw-r--r--fs/btrfs/super.c1
-rw-r--r--fs/btrfs/volumes.c31
-rw-r--r--fs/btrfs/volumes.h1
-rw-r--r--fs/btrfs/zoned.c2
8 files changed, 56 insertions, 2 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c0a30bb213d7a..27d7a24ff97ae 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3591,6 +3591,13 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
}
}
+ ret = btrfs_init_writeback_bio_size(fs_info);
+ if (ret) {
+ btrfs_err(fs_info, "failed to get optimum writeback size: %d",
+ ret);
+ goto fail_sysfs;
+ }
+
btrfs_free_zone_cache(fs_info);
btrfs_check_active_zone_reservation(fs_info);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 391fad41c3b6d..f87398910e59d 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2108,7 +2108,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
locked_ref = btrfs_select_ref_head(fs_info, delayed_refs);
if (IS_ERR_OR_NULL(locked_ref)) {
if (PTR_ERR(locked_ref) == -EAGAIN) {
- continue;
+ count++;
+ goto again;
} else {
break;
}
@@ -2156,7 +2157,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
* Either success case or btrfs_run_delayed_refs_for_head
* returned -EAGAIN, meaning we need to select another head
*/
-
+again:
locked_ref = NULL;
cond_resched();
} while ((min_bytes != U64_MAX && bytes_processed < min_bytes) ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 2275189b78605..0c6342995a00f 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -857,6 +857,16 @@ static void submit_extent_folio(struct btrfs_bio_ctrl *bio_ctrl,
/* Ordered extent boundary: move on to a new bio. */
if (bio_ctrl->len_to_oe_boundary == 0)
submit_one_bio(bio_ctrl);
+ /*
+ * If we have accumulated decent amount of IO, send it to the
+ * block layer so that IO can run while we are accumulating
+ * more folios to write.
+ */
+ else if (bio_ctrl->wbc &&
+ bio_ctrl->bbio->bio.bi_iter.bi_size >=
+ inode->root->fs_info->writeback_bio_size)
+ submit_one_bio(bio_ctrl);
+
} while (size);
}
diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
index a8aa086a4df86..1782f228c45c0 100644
--- a/fs/btrfs/fs.h
+++ b/fs/btrfs/fs.h
@@ -881,6 +881,7 @@ struct btrfs_fs_info {
u32 block_min_order;
u32 block_max_order;
u32 stripesize;
+ u32 writeback_bio_size;
u32 csum_size;
u32 csums_per_leaf;
u32 csum_type;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index b26aa9169e838..64514d600eec7 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1873,6 +1873,7 @@ static int btrfs_get_tree_super(struct fs_context *fc)
fs_info->fs_devices = fs_devices;
mutex_unlock(&uuid_mutex);
+ fc->sb_flags |= SB_NOSEC;
sb = sget_fc(fc, btrfs_fc_test_super, set_anon_super_fc);
if (IS_ERR(sb)) {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a88e68f905646..ed009bc9da2ad 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -8179,6 +8179,37 @@ out:
return ret;
}
+int btrfs_init_writeback_bio_size(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+ struct btrfs_device *device;
+ u32 writeback_bio_size = fs_info->sectorsize;
+
+ mutex_lock(&fs_devices->device_list_mutex);
+ /*
+ * Let's take maximum over optimal request sizes for all devices. For
+ * RAID profiles writeback will submit stripe (64k) sized bios anyway
+ * so our value doesn't matter and for simple profiles this is a good
+ * approximation of sensible IO chunking.
+ */
+ list_for_each_entry(device, &fs_devices->devices, dev_list) {
+ struct request_queue *queue;
+ unsigned int io_opt;
+
+ if (!device->bdev || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
+ continue;
+ queue = bdev_get_queue(device->bdev);
+ io_opt = queue_io_opt(queue) ? :
+ queue_max_sectors(queue) << SECTOR_SHIFT;
+ writeback_bio_size = max(writeback_bio_size, io_opt);
+ }
+ mutex_unlock(&fs_devices->device_list_mutex);
+
+ fs_info->writeback_bio_size = writeback_bio_size;
+
+ return 0;
+}
+
static int update_dev_stat_item(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 0082c166af91f..96904d18f686b 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -784,6 +784,7 @@ int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
struct btrfs_ioctl_get_dev_stats *stats);
int btrfs_init_devices_late(struct btrfs_fs_info *fs_info);
int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info);
+int btrfs_init_writeback_bio_size(struct btrfs_fs_info *fs_info);
int btrfs_run_dev_stats(struct btrfs_trans_handle *trans);
void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_device *srcdev);
void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev);
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 16dd87aa06f20..5f75cf0e14b95 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -131,8 +131,10 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
u64 bytenr = ALIGN_DOWN(zone_end, BTRFS_SUPER_INFO_SIZE) -
BTRFS_SUPER_INFO_SIZE;
+ filemap_invalidate_lock(mapping);
page[i] = read_cache_page_gfp(mapping,
bytenr >> PAGE_SHIFT, GFP_NOFS);
+ filemap_invalidate_unlock(mapping);
if (IS_ERR(page[i])) {
if (i == 1)
btrfs_release_disk_super(super[0]);