]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: convert perag lookup to xarray
authorChristoph Hellwig <hch@lst.de>
Thu, 29 Aug 2024 04:08:40 +0000 (07:08 +0300)
committerChandan Babu R <chandanbabu@kernel.org>
Tue, 3 Sep 2024 04:37:46 +0000 (10:07 +0530)
Convert the perag lookup from the legacy radix tree to the xarray,
which allows for much nicer iteration and bulk lookup semantics.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
fs/xfs/libxfs/xfs_ag.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_super.c

index 87f00f0180846f869b182cb696ed9540f557b262..5f0494702e0b55a2343a3f8e08ed33e5e1974f81 100644 (file)
@@ -46,7 +46,7 @@ xfs_perag_get(
        struct xfs_perag        *pag;
 
        rcu_read_lock();
-       pag = radix_tree_lookup(&mp->m_perag_tree, agno);
+       pag = xa_load(&mp->m_perags, agno);
        if (pag) {
                trace_xfs_perag_get(pag, _RET_IP_);
                ASSERT(atomic_read(&pag->pag_ref) >= 0);
@@ -92,7 +92,7 @@ xfs_perag_grab(
        struct xfs_perag        *pag;
 
        rcu_read_lock();
-       pag = radix_tree_lookup(&mp->m_perag_tree, agno);
+       pag = xa_load(&mp->m_perags, agno);
        if (pag) {
                trace_xfs_perag_grab(pag, _RET_IP_);
                if (!atomic_inc_not_zero(&pag->pag_active_ref))
@@ -195,9 +195,7 @@ xfs_free_perag(
        xfs_agnumber_t          agno;
 
        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);
                XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0);
                xfs_defer_drain_free(&pag->pag_intents_drain);
@@ -286,9 +284,7 @@ xfs_free_unused_perag_range(
        xfs_agnumber_t          index;
 
        for (index = agstart; index < agend; index++) {
-               spin_lock(&mp->m_perag_lock);
-               pag = radix_tree_delete(&mp->m_perag_tree, index);
-               spin_unlock(&mp->m_perag_lock);
+               pag = xa_erase(&mp->m_perags, index);
                if (!pag)
                        break;
                xfs_buf_cache_destroy(&pag->pag_bcache);
@@ -329,20 +325,11 @@ xfs_initialize_perag(
                pag->pag_agno = index;
                pag->pag_mount = mp;
 
-               error = radix_tree_preload(GFP_KERNEL | __GFP_RETRY_MAYFAIL);
-               if (error)
-                       goto out_free_pag;
-
-               spin_lock(&mp->m_perag_lock);
-               if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
-                       WARN_ON_ONCE(1);
-                       spin_unlock(&mp->m_perag_lock);
-                       radix_tree_preload_end();
-                       error = -EEXIST;
+               error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);
+               if (error) {
+                       WARN_ON_ONCE(error == -EBUSY);
                        goto out_free_pag;
                }
-               spin_unlock(&mp->m_perag_lock);
-               radix_tree_preload_end();
 
 #ifdef __KERNEL__
                /* Place kernel structure only init below this point. */
@@ -390,9 +377,7 @@ xfs_initialize_perag(
 
 out_remove_pag:
        xfs_defer_drain_free(&pag->pag_intents_drain);
-       spin_lock(&mp->m_perag_lock);
-       radix_tree_delete(&mp->m_perag_tree, index);
-       spin_unlock(&mp->m_perag_lock);
+       pag = xa_erase(&mp->m_perags, index);
 out_free_pag:
        kfree(pag);
 out_unwind_new_pags:
index 6dd88c3cdf449e39223d5ab24c21ba05bde69736..ba9d4c8581831b303ec8b2952b64ad71bebf1c83 100644 (file)
@@ -65,6 +65,18 @@ static int xfs_icwalk_ag(struct xfs_perag *pag,
                                         XFS_ICWALK_FLAG_RECLAIM_SICK | \
                                         XFS_ICWALK_FLAG_UNION)
 
+/* Marks for the perag xarray */
+#define XFS_PERAG_RECLAIM_MARK XA_MARK_0
+#define XFS_PERAG_BLOCKGC_MARK XA_MARK_1
+
+static inline xa_mark_t ici_tag_to_mark(unsigned int tag)
+{
+       if (tag == XFS_ICI_RECLAIM_TAG)
+               return XFS_PERAG_RECLAIM_MARK;
+       ASSERT(tag == XFS_ICI_BLOCKGC_TAG);
+       return XFS_PERAG_BLOCKGC_MARK;
+}
+
 /*
  * Allocate and initialise an xfs_inode.
  */
@@ -191,7 +203,7 @@ xfs_reclaim_work_queue(
 {
 
        rcu_read_lock();
-       if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
+       if (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
                queue_delayed_work(mp->m_reclaim_workqueue, &mp->m_reclaim_work,
                        msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
        }
@@ -241,9 +253,7 @@ xfs_perag_set_inode_tag(
                return;
 
        /* propagate the tag up into the perag radix tree */
-       spin_lock(&mp->m_perag_lock);
-       radix_tree_tag_set(&mp->m_perag_tree, pag->pag_agno, tag);
-       spin_unlock(&mp->m_perag_lock);
+       xa_set_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
 
        /* start background work */
        switch (tag) {
@@ -285,9 +295,7 @@ xfs_perag_clear_inode_tag(
                return;
 
        /* clear the tag from the perag radix tree */
-       spin_lock(&mp->m_perag_lock);
-       radix_tree_tag_clear(&mp->m_perag_tree, pag->pag_agno, tag);
-       spin_unlock(&mp->m_perag_lock);
+       xa_clear_mark(&mp->m_perags, pag->pag_agno, ici_tag_to_mark(tag));
 
        trace_xfs_perag_clear_inode_tag(pag, _RET_IP_);
 }
@@ -302,7 +310,6 @@ xfs_perag_get_next_tag(
        unsigned int            tag)
 {
        unsigned long           index = 0;
-       int                     found;
 
        if (pag) {
                index = pag->pag_agno + 1;
@@ -310,14 +317,11 @@ xfs_perag_get_next_tag(
        }
 
        rcu_read_lock();
-       found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
-                                       (void **)&pag, index, 1, tag);
-       if (found <= 0) {
-               rcu_read_unlock();
-               return NULL;
+       pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
+       if (pag) {
+               trace_xfs_perag_get_next_tag(pag, _RET_IP_);
+               atomic_inc(&pag->pag_ref);
        }
-       trace_xfs_perag_get_next_tag(pag, _RET_IP_);
-       atomic_inc(&pag->pag_ref);
        rcu_read_unlock();
        return pag;
 }
@@ -332,7 +336,6 @@ xfs_perag_grab_next_tag(
        int                     tag)
 {
        unsigned long           index = 0;
-       int                     found;
 
        if (pag) {
                index = pag->pag_agno + 1;
@@ -340,15 +343,12 @@ xfs_perag_grab_next_tag(
        }
 
        rcu_read_lock();
-       found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
-                                       (void **)&pag, index, 1, tag);
-       if (found <= 0) {
-               rcu_read_unlock();
-               return NULL;
+       pag = xa_find(&mp->m_perags, &index, ULONG_MAX, ici_tag_to_mark(tag));
+       if (pag) {
+               trace_xfs_perag_grab_next_tag(pag, _RET_IP_);
+               if (!atomic_inc_not_zero(&pag->pag_active_ref))
+                       pag = NULL;
        }
-       trace_xfs_perag_grab_next_tag(pag, _RET_IP_);
-       if (!atomic_inc_not_zero(&pag->pag_active_ref))
-               pag = NULL;
        rcu_read_unlock();
        return pag;
 }
@@ -1038,7 +1038,7 @@ xfs_reclaim_inodes(
        if (xfs_want_reclaim_sick(mp))
                icw.icw_flags |= XFS_ICWALK_FLAG_RECLAIM_SICK;
 
-       while (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
+       while (xa_marked(&mp->m_perags, XFS_PERAG_RECLAIM_MARK)) {
                xfs_ail_push_all_sync(mp->m_ail);
                xfs_icwalk(mp, XFS_ICWALK_RECLAIM, &icw);
        }
index 7bf635cccaa1c39fa85d3cd8acd5cfab9cd2812e..96496f39f551ae29ed10ce4c0f9107287bc69e2a 100644 (file)
@@ -208,8 +208,7 @@ typedef struct xfs_mount {
         */
        atomic64_t              m_allocbt_blks;
 
-       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 */
        uint64_t                m_resblks;      /* total reserved blocks */
        uint64_t                m_resblks_avail;/* available reserved blocks */
        uint64_t                m_resblks_save; /* reserved blks @ remount,ro */
index 904e7bf846d7b473572a03ac54923bdf26529b6c..26767745d9fd01d60d7da807a92165113d97dbab 100644 (file)
@@ -2009,8 +2009,7 @@ static int xfs_init_fs_context(
                return -ENOMEM;
 
        spin_lock_init(&mp->m_sb_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);
        INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
        INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);