From: Matthew Wilcox Date: Tue, 25 Sep 2018 22:52:51 +0000 (-0400) Subject: xfs: Convert m_perag_tree to XArray X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=0634546222b4b532eeb38b460dbe7156f9f92500;p=users%2Fwilly%2Fxarray.git xfs: Convert m_perag_tree to XArray This is a relatively straightforward conversion to the XArray API. I've renamed a few tags to marks in this patch; more will follow in later patches. Signed-off-by: Matthew Wilcox --- diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index a08dd8f40346f..7639bf9b87372 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -43,7 +43,7 @@ xfs_perag_get( int ref = 0; rcu_read_lock(); - pag = radix_tree_lookup(&mp->m_perag_tree, agno); + pag = xa_load(&mp->m_perags, agno); if (pag) { ASSERT(atomic_read(&pag->pag_ref) >= 0); ref = atomic_inc_return(&pag->pag_ref); @@ -54,22 +54,21 @@ xfs_perag_get( } /* - * search from @first to find the next perag with the given tag set. + * search from @first to find the next perag with the given mark set. */ struct xfs_perag * -xfs_perag_get_tag( +xfs_perag_get_mark( struct xfs_mount *mp, xfs_agnumber_t first, - int tag) + xa_mark_t mark) { struct xfs_perag *pag; - int found; int ref; + unsigned long index = first; rcu_read_lock(); - found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, - (void **)&pag, first, 1, tag); - if (found <= 0) { + pag = xa_find(&mp->m_perags, &index, ULONG_MAX, mark); + if (!pag) { rcu_read_unlock(); return NULL; } diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h index 92465a9a51620..2459f5f7d663a 100644 --- a/fs/xfs/libxfs/xfs_sb.h +++ b/fs/xfs/libxfs/xfs_sb.h @@ -17,8 +17,8 @@ struct xfs_perag; * perag get/put wrappers for ref counting */ extern struct xfs_perag *xfs_perag_get(struct xfs_mount *, xfs_agnumber_t); -extern struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *, xfs_agnumber_t, - int tag); +extern struct xfs_perag *xfs_perag_get_mark(struct xfs_mount *, xfs_agnumber_t, + xa_mark_t mark); extern void xfs_perag_put(struct xfs_perag *pag); extern int xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t); diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 0b0fd10a36d4d..2484dceab35ac 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -149,13 +149,10 @@ static void xfs_reclaim_work_queue( struct xfs_mount *mp) { - - rcu_read_lock(); - if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) { + if (xa_marked(&mp->m_perags, XFS_ICI_RECLAIM_MARK)) { queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work, msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10)); } - rcu_read_unlock(); } /* @@ -186,11 +183,8 @@ xfs_perag_set_reclaim_tag( if (pag->pag_ici_reclaimable++) return; - /* propagate the reclaim tag up into the perag radix tree */ - spin_lock(&mp->m_perag_lock); - radix_tree_tag_set(&mp->m_perag_tree, pag->pag_agno, - XFS_ICI_RECLAIM_TAG); - spin_unlock(&mp->m_perag_lock); + /* propagate the reclaim tag up into the perag xarray */ + xa_set_mark(&mp->m_perags, pag->pag_agno, XFS_ICI_RECLAIM_MARK); /* schedule periodic background inode reclaim */ xfs_reclaim_work_queue(mp); @@ -208,11 +202,8 @@ xfs_perag_clear_reclaim_tag( if (--pag->pag_ici_reclaimable) return; - /* clear the reclaim tag from the perag radix tree */ - spin_lock(&mp->m_perag_lock); - radix_tree_tag_clear(&mp->m_perag_tree, pag->pag_agno, - XFS_ICI_RECLAIM_TAG); - spin_unlock(&mp->m_perag_lock); + /* clear the reclaim tag from the perag xarray */ + xa_clear_mark(&mp->m_perags, pag->pag_agno, XFS_ICI_RECLAIM_MARK); trace_xfs_perag_clear_reclaim(mp, pag->pag_agno, -1, _RET_IP_); } @@ -893,12 +884,10 @@ void xfs_queue_eofblocks( struct xfs_mount *mp) { - rcu_read_lock(); - if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_EOFBLOCKS_TAG)) + if (xa_marked(&mp->m_perags, XFS_ICI_EOFBLOCKS_MARK)) queue_delayed_work(mp->m_eofblocks_workqueue, &mp->m_eofblocks_work, msecs_to_jiffies(xfs_eofb_secs * 1000)); - rcu_read_unlock(); } void @@ -920,12 +909,10 @@ void xfs_queue_cowblocks( struct xfs_mount *mp) { - rcu_read_lock(); - if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_COWBLOCKS_TAG)) + if (xa_marked(&mp->m_perags, XFS_ICI_COWBLOCKS_MARK)) queue_delayed_work(mp->m_eofblocks_workqueue, &mp->m_cowblocks_work, msecs_to_jiffies(xfs_cowb_secs * 1000)); - rcu_read_unlock(); } void @@ -993,7 +980,7 @@ xfs_inode_ag_iterator_tag( xfs_agnumber_t ag; ag = 0; - while ((pag = xfs_perag_get_tag(mp, ag, tag))) { + while ((pag = xfs_perag_get_mark(mp, ag, tag))) { ag = pag->pag_agno + 1; error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag, 0); @@ -1250,7 +1237,7 @@ xfs_reclaim_inodes_ag( restart: ag = 0; skipped = 0; - while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) { + while ((pag = xfs_perag_get_mark(mp, ag, XFS_ICI_RECLAIM_MARK))) { unsigned long first_index = 0; int done = 0; int nr_found = 0; @@ -1397,7 +1384,7 @@ xfs_reclaim_inodes_count( xfs_agnumber_t ag = 0; int reclaimable = 0; - while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) { + while ((pag = xfs_perag_get_mark(mp, ag, XFS_ICI_RECLAIM_MARK))) { ag = pag->pag_agno + 1; reclaimable += pag->pag_ici_reclaimable; xfs_perag_put(pag); @@ -1598,40 +1585,38 @@ xfs_iflag_for_tag( } static void -__xfs_inode_set_blocks_tag( +__xfs_inode_set_blocks_mark( xfs_inode_t *ip, void (*execute)(struct xfs_mount *mp), void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, int error, unsigned long caller_ip), - int tag) + xa_mark_t mark) { struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; - int tagged; + int marked; /* - * Don't bother locking the AG and looking up in the radix trees - * if we already know that we have the tag set. + * Don't bother locking the AG and looking up in the xarray + * if we already know that we have the mark set. */ - if (ip->i_flags & xfs_iflag_for_tag(tag)) + if (ip->i_flags & xfs_iflag_for_tag(mark)) return; spin_lock(&ip->i_flags_lock); - ip->i_flags |= xfs_iflag_for_tag(tag); + ip->i_flags |= xfs_iflag_for_tag(mark); spin_unlock(&ip->i_flags_lock); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); - tagged = radix_tree_tagged(&pag->pag_ici_root, tag); + marked = radix_tree_tagged(&pag->pag_ici_root, mark); radix_tree_tag_set(&pag->pag_ici_root, - XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), tag); - if (!tagged) { - /* propagate the eofblocks tag up into the perag radix tree */ - spin_lock(&ip->i_mount->m_perag_lock); - radix_tree_tag_set(&ip->i_mount->m_perag_tree, + XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), mark); + if (!marked) { + /* propagate the eofblocks mark up into the perag xarray */ + xa_set_mark(&ip->i_mount->m_perags, XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), - tag); - spin_unlock(&ip->i_mount->m_perag_lock); + mark); /* kick off background trimming */ execute(ip->i_mount); @@ -1648,37 +1633,35 @@ xfs_inode_set_eofblocks_tag( xfs_inode_t *ip) { trace_xfs_inode_set_eofblocks_tag(ip); - return __xfs_inode_set_blocks_tag(ip, xfs_queue_eofblocks, + return __xfs_inode_set_blocks_mark(ip, xfs_queue_eofblocks, trace_xfs_perag_set_eofblocks, - XFS_ICI_EOFBLOCKS_TAG); + XFS_ICI_EOFBLOCKS_MARK); } static void -__xfs_inode_clear_blocks_tag( +__xfs_inode_clear_blocks_mark( xfs_inode_t *ip, void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, int error, unsigned long caller_ip), - int tag) + xa_mark_t mark) { struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; spin_lock(&ip->i_flags_lock); - ip->i_flags &= ~xfs_iflag_for_tag(tag); + ip->i_flags &= ~xfs_iflag_for_tag(mark); spin_unlock(&ip->i_flags_lock); pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); radix_tree_tag_clear(&pag->pag_ici_root, - XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), tag); - if (!radix_tree_tagged(&pag->pag_ici_root, tag)) { - /* clear the eofblocks tag from the perag radix tree */ - spin_lock(&ip->i_mount->m_perag_lock); - radix_tree_tag_clear(&ip->i_mount->m_perag_tree, + XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), mark); + if (!radix_tree_tagged(&pag->pag_ici_root, mark)) { + /* clear the eofblocks mark from the perag xarray */ + xa_clear_mark(&ip->i_mount->m_perags, XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), - tag); - spin_unlock(&ip->i_mount->m_perag_lock); + mark); clear_tp(ip->i_mount, pag->pag_agno, -1, _RET_IP_); } @@ -1691,8 +1674,9 @@ xfs_inode_clear_eofblocks_tag( xfs_inode_t *ip) { trace_xfs_inode_clear_eofblocks_tag(ip); - return __xfs_inode_clear_blocks_tag(ip, - trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG); + return __xfs_inode_clear_blocks_mark(ip, + trace_xfs_perag_clear_eofblocks, + XFS_ICI_EOFBLOCKS_MARK); } /* @@ -1804,9 +1788,9 @@ xfs_inode_set_cowblocks_tag( xfs_inode_t *ip) { trace_xfs_inode_set_cowblocks_tag(ip); - return __xfs_inode_set_blocks_tag(ip, xfs_queue_cowblocks, + return __xfs_inode_set_blocks_mark(ip, xfs_queue_cowblocks, trace_xfs_perag_set_cowblocks, - XFS_ICI_COWBLOCKS_TAG); + XFS_ICI_COWBLOCKS_MARK); } void @@ -1814,8 +1798,9 @@ xfs_inode_clear_cowblocks_tag( xfs_inode_t *ip) { trace_xfs_inode_clear_cowblocks_tag(ip); - return __xfs_inode_clear_blocks_tag(ip, - trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG); + return __xfs_inode_clear_blocks_mark(ip, + trace_xfs_perag_clear_cowblocks, + XFS_ICI_COWBLOCKS_MARK); } /* Disable post-EOF and CoW block auto-reclamation. */ diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 48f1fd2bb6ad8..cc786b109e054 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -21,13 +21,16 @@ struct xfs_eofblocks { #define SYNC_TRYLOCK 0x0002 /* only try to lock inodes */ /* - * tags for inode radix tree + * marks for inode xarray */ #define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup in xfs_inode_ag_iterator */ #define XFS_ICI_RECLAIM_TAG 0 /* inode is to be reclaimed */ #define XFS_ICI_EOFBLOCKS_TAG 1 /* inode has blocks beyond EOF */ #define XFS_ICI_COWBLOCKS_TAG 2 /* inode can have cow blocks to gc */ +#define XFS_ICI_RECLAIM_MARK XA_MARK_0 /* inode is to be reclaimed */ +#define XFS_ICI_EOFBLOCKS_MARK XA_MARK_1 /* inode has blocks beyond EOF */ +#define XFS_ICI_COWBLOCKS_MARK XA_MARK_2 /* inode can have cow blocks to gc */ /* * Flags for xfs_iget() diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 322da69092909..73a741f2e4a77 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -141,9 +141,7 @@ xfs_free_perag( struct xfs_perag *pag; for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { - spin_lock(&mp->m_perag_lock); - pag = radix_tree_delete(&mp->m_perag_tree, agno); - spin_unlock(&mp->m_perag_lock); + pag = xa_erase(&mp->m_perags, agno); ASSERT(pag); ASSERT(atomic_read(&pag->pag_ref) == 0); xfs_iunlink_destroy(pag); @@ -183,7 +181,7 @@ xfs_initialize_perag( int error = -ENOMEM; /* - * Walk the current per-ag tree so we don't try to initialise AGs + * Walk the current per-ag array so we don't try to initialise AGs * that already exist (growfs case). Allocate and insert all the * AGs we don't find ready for initialisation. */ @@ -209,19 +207,9 @@ xfs_initialize_perag( pag->pagb_count = 0; pag->pagb_tree = RB_ROOT; - if (radix_tree_preload(GFP_NOFS)) - goto out_hash_destroy; - - spin_lock(&mp->m_perag_lock); - if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { - BUG(); - spin_unlock(&mp->m_perag_lock); - radix_tree_preload_end(); - error = -EEXIST; + error = xa_err(xa_store(&mp->m_perags, index, pag, GFP_NOFS)); + if (error) goto out_hash_destroy; - } - spin_unlock(&mp->m_perag_lock); - radix_tree_preload_end(); /* first new pag is fully initialized */ if (first_initialised == NULLAGNUMBER) first_initialised = index; @@ -247,7 +235,7 @@ out_free_pag: out_unwind_new_pags: /* unwind any prior newly initialized pags */ for (index = first_initialised; index < agcount; index++) { - pag = radix_tree_delete(&mp->m_perag_tree, index); + pag = xa_erase(&mp->m_perags, index); if (!pag) break; xfs_buf_hash_destroy(pag); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 4adb6837439ac..05e34dffe28b6 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -145,8 +145,7 @@ typedef struct xfs_mount { xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ uint m_alloc_set_aside; /* space we can't use */ uint m_ag_max_usable; /* max space per AG */ - struct radix_tree_root m_perag_tree; /* per-ag accounting info */ - spinlock_t m_perag_lock; /* lock for m_perag_tree */ + struct xarray m_perags; /* per-ag accounting info */ struct mutex m_growlock; /* growfs mutex */ int m_fixedfsid[2]; /* unchanged for life of FS */ uint64_t m_flags; /* global mount flags */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index f9450235533cc..ca6de89cd0c74 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1553,8 +1553,7 @@ xfs_mount_alloc( mp->m_super = sb; spin_lock_init(&mp->m_sb_lock); spin_lock_init(&mp->m_agirotor_lock); - INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); - spin_lock_init(&mp->m_perag_lock); + xa_init(&mp->m_perags); mutex_init(&mp->m_growlock); atomic_set(&mp->m_active_trans, 0); INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);