diff mbox series

[RFC,3/3] xfs: use the parallel writeback infra per AG

Message ID 20250212103634.448437-4-kundan.kumar@samsung.com (mailing list archive)
State New
Headers show
Series [RFC,1/3] writeback: add parallel writeback infrastructure | expand

Commit Message

Kundan Kumar Feb. 12, 2025, 10:36 a.m. UTC
The bdi_writeback now provides NR_WB_CTX number of writeback contexts
stored in the wb_ctx_list. This allows each allocation group in xfs to
utilize a distinct writeback context. To implement this, the following
changes have been made:
- Adjust xfs to assign a unique writeback context to each allocation group.
- Include a super_operations function pointer within super_operations to
retrieve the writeback context associated with an inode. Currently it is
implemented by xfs. It can be extended to other FS in future.

Signed-off-by: Kundan Kumar <kundan.kumar@samsung.com>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
 fs/fs-writeback.c      | 34 ++++++++++++++++++++++------------
 fs/xfs/libxfs/xfs_ag.c | 16 ++++++++++++++++
 fs/xfs/libxfs/xfs_ag.h |  1 +
 fs/xfs/xfs_super.c     | 20 ++++++++++++++++++++
 include/linux/fs.h     |  1 +
 5 files changed, 60 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8f7dd5d10085..75a6f5c50ee7 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2712,7 +2712,7 @@  void __mark_inode_dirty(struct inode *inode, int flags)
 		 */
 		if (!was_dirty) {
 			/* Schedule writeback on first wb_ctx */
-			struct wb_ctx *p_wb_ctx = ctx_wb_struct(wb, 0);
+			struct wb_ctx *p_wb_ctx;
 			struct list_head *dirty_list;
 			bool wakeup_bdi = false;
 
@@ -2720,17 +2720,27 @@  void __mark_inode_dirty(struct inode *inode, int flags)
 			if (dirtytime)
 				inode->dirtied_time_when = jiffies;
 
-
-			if (inode->i_state & I_DIRTY)
-				dirty_list = ctx_b_dirty_list(wb, 0);
-			else
-				dirty_list = ctx_b_dirty_time_list(wb,
-								   0);
-
-			wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
-								   dirty_list,
-								   p_wb_ctx);
-
+			if (!sb->s_op->get_wb_ctx) {
+				p_wb_ctx = ctx_wb_struct(wb, 0);
+
+				if (inode->i_state & I_DIRTY)
+					dirty_list = ctx_b_dirty_list(wb, 0);
+				else
+					dirty_list = ctx_b_dirty_time_list(wb,
+									   0);
+				wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
+									   dirty_list,
+									   p_wb_ctx);
+			} else {
+				p_wb_ctx = sb->s_op->get_wb_ctx(inode);
+				if (inode->i_state & I_DIRTY)
+					dirty_list = &p_wb_ctx->pctx_b_dirty;
+				else
+					dirty_list = &p_wb_ctx->pctx_b_dirty_time;
+				wakeup_bdi = inode_io_list_move_locked_ctx(inode, wb,
+									   dirty_list,
+									   p_wb_ctx);
+			}
 			spin_unlock(&wb->list_lock);
 			spin_unlock(&inode->i_lock);
 			trace_writeback_dirty_inode_enqueue(inode);
diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c
index b59cb461e096..5d6551e5522e 100644
--- a/fs/xfs/libxfs/xfs_ag.c
+++ b/fs/xfs/libxfs/xfs_ag.c
@@ -214,6 +214,11 @@  xfs_update_last_ag_size(
 	return 0;
 }
 
+static struct backing_dev_info *xfs_mp_to_bdi(struct xfs_mount *mp)
+{
+	return mp->m_super->s_bdi;
+}
+
 static int
 xfs_perag_alloc(
 	struct xfs_mount	*mp,
@@ -221,12 +226,22 @@  xfs_perag_alloc(
 	xfs_agnumber_t		agcount,
 	xfs_rfsblock_t		dblocks)
 {
+	struct backing_dev_info *bdi = xfs_mp_to_bdi(mp);
+	struct bdi_writeback *wb = &bdi->wb;
+	struct wb_ctx *p_wb_ctx;
 	struct xfs_perag	*pag;
 	int			error;
 
 	pag = kzalloc(sizeof(*pag), GFP_KERNEL);
 	if (!pag)
 		return -ENOMEM;
+	spin_lock(&wb->list_lock);
+	if (wb->wb_idx >= NR_WB_CTX)
+		wb->wb_idx = 0;
+	p_wb_ctx = &wb->wb_ctx_list[wb->wb_idx];
+	wb->wb_idx++;
+	spin_unlock(&wb->list_lock);
+	pag->pag_wb_ctx = p_wb_ctx;
 
 #ifdef __KERNEL__
 	/* Place kernel structure only init below this point. */
@@ -261,6 +276,7 @@  xfs_perag_alloc(
 	return error;
 }
 
+
 int
 xfs_initialize_perag(
 	struct xfs_mount	*mp,
diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h
index 1f24cfa27321..5c25850e94dd 100644
--- a/fs/xfs/libxfs/xfs_ag.h
+++ b/fs/xfs/libxfs/xfs_ag.h
@@ -89,6 +89,7 @@  struct xfs_perag {
 
 	/* background prealloc block trimming */
 	struct delayed_work	pag_blockgc_work;
+	struct wb_ctx		*pag_wb_ctx;
 #endif /* __KERNEL__ */
 };
 
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index d92d7a07ea89..7416e1ad45e9 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1210,6 +1210,25 @@  xfs_fs_shutdown(
 	xfs_force_shutdown(XFS_M(sb), SHUTDOWN_DEVICE_REMOVED);
 }
 
+static struct wb_ctx *
+		xfs_get_wb_ctx(
+		struct inode *inode)
+{
+	struct xfs_inode *xfs_inode = XFS_I(inode);
+	struct xfs_perag *pag = xfs_perag_get(xfs_inode->i_mount,
+			XFS_INO_TO_AGNO(xfs_inode->i_mount, xfs_inode->i_ino));
+	struct wb_ctx *p_wb_ctx;
+
+	if (!pag) {
+		/* There had better still be a perag structure! */
+		ASSERT(0);
+		return NULL;
+	}
+	p_wb_ctx = pag->pag_wb_ctx;
+	xfs_perag_put(pag);
+	return p_wb_ctx;
+}
+
 static const struct super_operations xfs_super_operations = {
 	.alloc_inode		= xfs_fs_alloc_inode,
 	.destroy_inode		= xfs_fs_destroy_inode,
@@ -1224,6 +1243,7 @@  static const struct super_operations xfs_super_operations = {
 	.nr_cached_objects	= xfs_fs_nr_cached_objects,
 	.free_cached_objects	= xfs_fs_free_cached_objects,
 	.shutdown		= xfs_fs_shutdown,
+	.get_wb_ctx		= xfs_get_wb_ctx,
 };
 
 static int
diff --git a/include/linux/fs.h b/include/linux/fs.h
index be3ad155ec9f..4f655daeb97f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2307,6 +2307,7 @@  struct super_operations {
 	long (*free_cached_objects)(struct super_block *,
 				    struct shrink_control *);
 	void (*shutdown)(struct super_block *sb);
+	struct wb_ctx *(*get_wb_ctx)(struct inode *);
 };
 
 /*