Introduce per-AG writeback worker infrastructure at mount time. This patch adds initialization and teardown only, without changing writeback behavior. Signed-off-by: Kundan Kumar Signed-off-by: Anuj Gupta --- fs/xfs/xfs_aops.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_aops.h | 3 ++ fs/xfs/xfs_mount.c | 2 ++ fs/xfs/xfs_mount.h | 10 ++++++ fs/xfs/xfs_super.c | 2 ++ 5 files changed, 96 insertions(+) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index a26f79815533..9d5b65922cd2 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -23,6 +23,23 @@ #include "xfs_zone_alloc.h" #include "xfs_rtgroup.h" +#define XFS_AG_TASK_POOL_MIN 1024 + +struct xfs_ag_wb_task { + struct list_head list; + struct xfs_inode *ip; + struct writeback_control wbc; + xfs_agnumber_t agno; +}; + +struct xfs_ag_wb { + struct delayed_work ag_work; + spinlock_t lock; + struct list_head task_list; + xfs_agnumber_t agno; + struct xfs_mount *mp; +}; + struct xfs_writepage_ctx { struct iomap_writepage_ctx ctx; unsigned int data_seq; @@ -666,6 +683,68 @@ static const struct iomap_writeback_ops xfs_zoned_writeback_ops = { .writeback_submit = xfs_zoned_writeback_submit, }; +void +xfs_init_ag_writeback(struct xfs_mount *mp) +{ + xfs_agnumber_t agno; + + mp->m_ag_wq = alloc_workqueue("xfs-ag-wb", WQ_UNBOUND | WQ_MEM_RECLAIM, + 0); + if (!mp->m_ag_wq) + return; + + mp->m_ag_wb = kcalloc(mp->m_sb.sb_agcount, + sizeof(struct xfs_ag_wb), + GFP_KERNEL); + + if (!mp->m_ag_wb) { + destroy_workqueue(mp->m_ag_wq); + mp->m_ag_wq = NULL; + return; + } + + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + struct xfs_ag_wb *awb = &mp->m_ag_wb[agno]; + + spin_lock_init(&awb->lock); + INIT_LIST_HEAD(&awb->task_list); + awb->agno = agno; + awb->mp = mp; + } + + mp->m_ag_task_cachep = kmem_cache_create("xfs_ag_wb_task", + sizeof(struct xfs_ag_wb_task), + 0, + SLAB_RECLAIM_ACCOUNT, + NULL); + + mp->m_ag_task_pool = mempool_create_slab_pool(XFS_AG_TASK_POOL_MIN, + mp->m_ag_task_cachep); + + if (!mp->m_ag_task_pool) { + kmem_cache_destroy(mp->m_ag_task_cachep); + mp->m_ag_task_cachep = NULL; + } +} + +void +xfs_destroy_ag_writeback(struct xfs_mount *mp) +{ + if (mp->m_ag_wq) { + flush_workqueue(mp->m_ag_wq); + destroy_workqueue(mp->m_ag_wq); + mp->m_ag_wq = NULL; + } + kfree(mp->m_ag_wb); + mp->m_ag_wb = NULL; + + mempool_destroy(mp->m_ag_task_pool); + mp->m_ag_task_pool = NULL; + + kmem_cache_destroy(mp->m_ag_task_cachep); + mp->m_ag_task_cachep = NULL; +} + STATIC int xfs_vm_writepages( struct address_space *mapping, diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 5a7a0f1a0b49..e84acb7e8ca8 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -12,4 +12,7 @@ extern const struct address_space_operations xfs_dax_aops; int xfs_setfilesize(struct xfs_inode *ip, xfs_off_t offset, size_t size); void xfs_end_bio(struct bio *bio); +void xfs_init_ag_writeback(struct xfs_mount *mp); +void xfs_destroy_ag_writeback(struct xfs_mount *mp); + #endif /* __XFS_AOPS_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 0953f6ae94ab..26224503c4bf 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1323,6 +1323,8 @@ xfs_unmountfs( xfs_qm_unmount(mp); + xfs_destroy_ag_writeback(mp); + /* * Unreserve any blocks we have so that when we unmount we don't account * the reserved free space as used. This is really only necessary for diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index b871dfde372b..c44155de2883 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -342,6 +342,16 @@ typedef struct xfs_mount { /* Hook to feed dirent updates to an active online repair. */ struct xfs_hooks m_dir_update_hooks; + + + /* global XFS AG writeback wq */ + struct workqueue_struct *m_ag_wq; + /* array of [sb_agcount] */ + struct xfs_ag_wb *m_ag_wb; + + /* task cache and pool */ + struct kmem_cache *m_ag_task_cachep; + mempool_t *m_ag_task_pool; } xfs_mount_t; #define M_IGEO(mp) (&(mp)->m_ino_geo) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bc71aa9dcee8..73f8d2942df4 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1765,6 +1765,8 @@ xfs_fs_fill_super( if (error) goto out_free_sb; + xfs_init_ag_writeback(mp); + /* * V4 support is undergoing deprecation. * -- 2.25.1