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 Signed-off-by: Anuj Gupta --- 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