Merge tag 'xarray-5.18' of git://git.infradead.org/users/willy/xarray
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Apr 2022 20:40:44 +0000 (13:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Apr 2022 20:40:44 +0000 (13:40 -0700)
Pull XArray updates from Matthew Wilcox:

 - Documentation update

 - Fix test-suite build after move of bitmap.h

 - Fix xas_create_range() when a large entry is already present

 - Fix xas_split() of a shadow entry

* tag 'xarray-5.18' of git://git.infradead.org/users/willy/xarray:
  XArray: Update the LRU list in xas_split()
  XArray: Fix xas_create_range() when multi-order entry present
  XArray: Include bitmap.h from xarray.h
  XArray: Document the locking requirement for the xa_state

1  2 
include/linux/xarray.h
lib/xarray.c

diff --combined include/linux/xarray.h
index bb52b786be1b74b65b0ad0a55d2ecd81f44f5351,66e28bc1a023f3a9974183cca231749d25476fd8..72feab5ea8d4a94d49ed48c531e2d74e9dbaac1d
@@@ -9,6 -9,7 +9,7 @@@
   * See Documentation/core-api/xarray.rst for how to use the XArray.
   */
  
+ #include <linux/bitmap.h>
  #include <linux/bug.h>
  #include <linux/compiler.h>
  #include <linux/gfp.h>
@@@ -1317,7 -1318,6 +1318,7 @@@ struct xa_state 
        struct xa_node *xa_node;
        struct xa_node *xa_alloc;
        xa_update_node_t xa_update;
 +      struct list_lru *xa_lru;
  };
  
  /*
        .xa_pad = 0,                                    \
        .xa_node = XAS_RESTART,                         \
        .xa_alloc = NULL,                               \
 -      .xa_update = NULL                               \
 +      .xa_update = NULL,                              \
 +      .xa_lru = NULL,                                 \
  }
  
  /**
@@@ -1633,11 -1632,6 +1634,11 @@@ static inline void xas_set_update(struc
        xas->xa_update = update;
  }
  
 +static inline void xas_set_lru(struct xa_state *xas, struct list_lru *lru)
 +{
 +      xas->xa_lru = lru;
 +}
 +
  /**
   * xas_next_entry() - Advance iterator to next present entry.
   * @xas: XArray operation state.
diff --combined lib/xarray.c
index b95e92598b9c4ed00b1a47f28d38b694ac8f5b81,88ca87435e3dad27eaa75aafdee37880a2397572..4acc88ea7c21744e6b1faa54af6f2029545a1b32
@@@ -302,7 -302,7 +302,7 @@@ bool xas_nomem(struct xa_state *xas, gf
        }
        if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT)
                gfp |= __GFP_ACCOUNT;
 -      xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
 +      xas->xa_alloc = kmem_cache_alloc_lru(radix_tree_node_cachep, xas->xa_lru, gfp);
        if (!xas->xa_alloc)
                return false;
        xas->xa_alloc->parent = NULL;
@@@ -334,10 -334,10 +334,10 @@@ static bool __xas_nomem(struct xa_stat
                gfp |= __GFP_ACCOUNT;
        if (gfpflags_allow_blocking(gfp)) {
                xas_unlock_type(xas, lock_type);
 -              xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
 +              xas->xa_alloc = kmem_cache_alloc_lru(radix_tree_node_cachep, xas->xa_lru, gfp);
                xas_lock_type(xas, lock_type);
        } else {
 -              xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
 +              xas->xa_alloc = kmem_cache_alloc_lru(radix_tree_node_cachep, xas->xa_lru, gfp);
        }
        if (!xas->xa_alloc)
                return false;
@@@ -371,7 -371,7 +371,7 @@@ static void *xas_alloc(struct xa_state 
                if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT)
                        gfp |= __GFP_ACCOUNT;
  
 -              node = kmem_cache_alloc(radix_tree_node_cachep, gfp);
 +              node = kmem_cache_alloc_lru(radix_tree_node_cachep, xas->xa_lru, gfp);
                if (!node) {
                        xas_set_err(xas, -ENOMEM);
                        return NULL;
@@@ -722,6 -722,8 +722,8 @@@ void xas_create_range(struct xa_state *
  
                for (;;) {
                        struct xa_node *node = xas->xa_node;
+                       if (node->shift >= shift)
+                               break;
                        xas->xa_node = xa_parent_locked(xas->xa, node);
                        xas->xa_offset = node->offset - 1;
                        if (node->offset != 0)
@@@ -1014,7 -1016,7 +1016,7 @@@ void xas_split_alloc(struct xa_state *x
                void *sibling = NULL;
                struct xa_node *node;
  
 -              node = kmem_cache_alloc(radix_tree_node_cachep, gfp);
 +              node = kmem_cache_alloc_lru(radix_tree_node_cachep, xas->xa_lru, gfp);
                if (!node)
                        goto nomem;
                node->array = xas->xa;
@@@ -1079,6 -1081,7 +1081,7 @@@ void xas_split(struct xa_state *xas, vo
                                        xa_mk_node(child));
                        if (xa_is_value(curr))
                                values--;
+                       xas_update(xas, child);
                } else {
                        unsigned int canon = offset - xas->xa_sibs;
  
        } while (offset-- > xas->xa_offset);
  
        node->nr_values += values;
+       xas_update(xas, node);
  }
  EXPORT_SYMBOL_GPL(xas_split);
  #endif