Affine inode to a writeback context. This helps in minimizing the filesytem fragmentation due to inode being processed by different threads.
To support parallel writeback, wire up a new superblock operation get_inode_wb_ctx(). Filesystems can override this callback and select desired writeback context for a inode. FS can use the wb context based on its geometry and also use 64 bit inode numbers. If a filesystem doesn't implement this callback, it defaults to DEFALT_WB_CTX = 0, maintaining its original behavior. An example implementation for XFS is provided, where XFS selects the writeback context based on its Allocation Group number. Signed-off-by: Anuj Gupta <anuj2...@samsung.com> Signed-off-by: Kundan Kumar <kundan.ku...@samsung.com> --- fs/fs-writeback.c | 3 ++- fs/xfs/xfs_super.c | 13 +++++++++++++ include/linux/backing-dev.h | 5 ++++- include/linux/fs.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 0715a7617391..56c048e22f72 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -265,7 +265,8 @@ void __inode_attach_wb(struct inode *inode, struct folio *folio) { struct backing_dev_info *bdi = inode_to_bdi(inode); struct bdi_writeback *wb = NULL; - struct bdi_writeback_ctx *bdi_writeback_ctx = bdi->wb_ctx[0]; + struct bdi_writeback_ctx *bdi_writeback_ctx = + fetch_bdi_writeback_ctx(inode); if (inode_cgwb_enabled(inode)) { struct cgroup_subsys_state *memcg_css; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bb0a82635a77..b3ec9141d902 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -53,6 +53,7 @@ #include <linux/magic.h> #include <linux/fs_context.h> #include <linux/fs_parser.h> +#include <linux/backing-dev.h> static const struct super_operations xfs_super_operations; @@ -1294,6 +1295,17 @@ xfs_fs_show_stats( return 0; } +static struct bdi_writeback_ctx * +xfs_get_inode_wb_ctx( + struct inode *inode) +{ + struct xfs_inode *ip = XFS_I(inode); + struct backing_dev_info *bdi = inode_to_bdi(inode); + xfs_agino_t agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino); + + return bdi->wb_ctx[agno % bdi->nr_wb_ctx]; +} + static const struct super_operations xfs_super_operations = { .alloc_inode = xfs_fs_alloc_inode, .destroy_inode = xfs_fs_destroy_inode, @@ -1310,6 +1322,7 @@ static const struct super_operations xfs_super_operations = { .free_cached_objects = xfs_fs_free_cached_objects, .shutdown = xfs_fs_shutdown, .show_stats = xfs_fs_show_stats, + .get_inode_wb_ctx = xfs_get_inode_wb_ctx, }; static int diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 951ab5497500..59bbb69d300c 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -148,6 +148,7 @@ static inline bool mapping_can_writeback(struct address_space *mapping) return inode_to_bdi(mapping->host)->capabilities & BDI_CAP_WRITEBACK; } +#define DEFAULT_WB_CTX 0 #define for_each_bdi_wb_ctx(bdi, wbctx) \ for (int __i = 0; __i < (bdi)->nr_wb_ctx \ && ((wbctx) = (bdi)->wb_ctx[__i]) != NULL; __i++) @@ -157,7 +158,9 @@ fetch_bdi_writeback_ctx(struct inode *inode) { struct backing_dev_info *bdi = inode_to_bdi(inode); - return bdi->wb_ctx[0]; + if (inode->i_sb->s_op->get_inode_wb_ctx) + return inode->i_sb->s_op->get_inode_wb_ctx(inode); + return bdi->wb_ctx[DEFAULT_WB_CTX]; } #ifdef CONFIG_CGROUP_WRITEBACK diff --git a/include/linux/fs.h b/include/linux/fs.h index 754fec84f350..5199b0d49fa5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2379,6 +2379,7 @@ struct super_operations { */ int (*remove_bdev)(struct super_block *sb, struct block_device *bdev); void (*shutdown)(struct super_block *sb); + struct bdi_writeback_ctx *(*get_inode_wb_ctx)(struct inode *inode); }; /* -- 2.25.1 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel