[PATCH v2 16/16] writeback: added XFS support for matching writeback count to allocation group count

Kundan Kumar
2025-10-14T12:11:41Z

Implemented bdi_inc_writeback() to increase the writeback context
count and called this function at XFS mount time to set the desired
count.

Signed-off-by: Kundan Kumar <kundan.kumar@samsung.com>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
fs/xfs/xfs_super.c | 2 ++
include/linux/backing-dev.h | 1 +
mm/backing-dev.c | 58 +++++++++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+)

diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index b3ec9141d902..aa97b59f53c6 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1783,6 +1783,8 @@ xfs_fs_fill_super(
if (error)
goto out_free_sb;

+ bdi_inc_writeback(sb->s_bdi, mp->m_sb.sb_agcount);
+
/*
* V4 support is undergoing deprecation.
*
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 14f53183b8d1..89a465e1964f 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -40,6 +40,7 @@ void wb_start_background_writeback(struct bdi_writeback *wb);
void wb_workfn(struct work_struct *work);

void wb_wait_for_completion(struct wb_completion *done);
+int bdi_inc_writeback(struct backing_dev_info *bdi, int nwriteback);

extern spinlock_t bdi_lock;
extern struct list_head bdi_list;
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 5bfb9bf3ce52..e450b3a9b952 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -1219,6 +1219,64 @@ struct backing_dev_info *bdi_alloc(int node_id)
}
EXPORT_SYMBOL(bdi_alloc);

+int bdi_inc_writeback(struct backing_dev_info *bdi, int nwritebacks)
+{
+ struct bdi_writeback_ctx **wb_ctx;
+ int ret = 0;
+
+ if (nwritebacks <= bdi->nr_wb_ctx)
+ return ret;
+
+ wb_ctx = kcalloc(nwritebacks, sizeof(struct bdi_writeback_ctx *),
+ GFP_KERNEL);
+ if (!wb_ctx)
+ return -ENOMEM;
+
+ for (int i = 0; i < bdi->nr_wb_ctx; i++)
+ wb_ctx[i] = bdi->wb_ctx[i];
+
+ for (int i = bdi->nr_wb_ctx; i < nwritebacks; i++) {
+ wb_ctx[i] = (struct bdi_writeback_ctx *)
+ kzalloc(sizeof(struct bdi_writeback_ctx), GFP_KERNEL);
+ if (!wb_ctx[i]) {
+ pr_err("Failed to allocate %d", i);
+ while (--i >= bdi->nr_wb_ctx)
+ kfree(wb_ctx[i]);
+ kfree(wb_ctx);
+ return -ENOMEM;
+ }
+ INIT_LIST_HEAD(&wb_ctx[i]->wb_list);
+ init_waitqueue_head(&wb_ctx[i]->wb_waitq);
+
+#ifdef CONFIG_CGROUP_WRITEBACK
+ INIT_RADIX_TREE(&wb_ctx[i]->cgwb_tree, GFP_ATOMIC);
+ init_rwsem(&wb_ctx[i]->wb_switch_rwsem);
+#endif
+ ret = wb_init(&wb_ctx[i]->wb, wb_ctx[i], bdi, GFP_KERNEL);
+ if (!ret) {
+#ifdef CONFIG_CGROUP_WRITEBACK
+ wb_ctx[i]->wb.memcg_css = &root_mem_cgroup->css;
+ wb_ctx[i]->wb.blkcg_css = blkcg_root_css;
+#endif
+ } else {
+ while (--i >= bdi->nr_wb_ctx)
+ kfree(wb_ctx[i]);
+ kfree(wb_ctx);
+ return ret;
+ }
+ cgwb_bdi_register(bdi, wb_ctx[i]);
+ set_bit(WB_registered, &wb_ctx[i]->wb.state);
+ }
+
+ spin_lock_bh(&bdi_lock);
+ kfree(bdi->wb_ctx);
+ bdi->wb_ctx = wb_ctx;
+ bdi->nr_wb_ctx = nwritebacks;
+ spin_unlock_bh(&bdi_lock);
+ return 0;
+}
+EXPORT_SYMBOL(bdi_inc_writeback);
+
static struct rb_node **bdi_lookup_rb_node(u64 id, struct rb_node **parentp)
{
struct rb_node **p = &bdi_tree.rb_node;
--
2.25.1