]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
lib/xarray: introduce a new helper xas_get_order
authorKairui Song <kasong@tencent.com>
Mon, 15 Apr 2024 17:18:55 +0000 (01:18 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 26 Apr 2024 03:56:09 +0000 (20:56 -0700)
It can be used after xas_load to check the order of loaded entries.
Compared to xa_get_order, it saves an XA_STATE and avoid a rewalk.

Added new test for xas_get_order, to make the test work, we have to export
xas_get_order with EXPORT_SYMBOL_GPL.

Also fix a sparse warning by checking the slot value with xa_entry instead
of accessing it directly, as suggested by Matthew Wilcox.

[kasong@tencent.com: simplify comment, sparse warning fix, per Matthew Wilcox]
Link: https://lkml.kernel.org/r/20240416071722.45997-4-ryncsn@gmail.com
Link: https://lkml.kernel.org/r/20240415171857.19244-4-ryncsn@gmail.com
Signed-off-by: Kairui Song <kasong@tencent.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/xarray.h
lib/test_xarray.c
lib/xarray.c

index cb571dfcf4b167ca1fbbe2edeeb4a96919955b9c..d9d479334c9e658260175b0d9994cdb0695ad373 100644 (file)
@@ -1548,6 +1548,7 @@ void xas_create_range(struct xa_state *);
 
 #ifdef CONFIG_XARRAY_MULTI
 int xa_get_order(struct xarray *, unsigned long index);
+int xas_get_order(struct xa_state *xas);
 void xas_split(struct xa_state *, void *entry, unsigned int order);
 void xas_split_alloc(struct xa_state *, void *entry, unsigned int order, gfp_t);
 #else
@@ -1556,6 +1557,11 @@ static inline int xa_get_order(struct xarray *xa, unsigned long index)
        return 0;
 }
 
+static inline int xas_get_order(struct xa_state *xas)
+{
+       return 0;
+}
+
 static inline void xas_split(struct xa_state *xas, void *entry,
                unsigned int order)
 {
index ebe2af2e072db390b2c65e149969c65544476e16..0efde8f9349088859721388f6b3b7a35f764325e 100644 (file)
@@ -1984,6 +1984,39 @@ static noinline void check_get_order(struct xarray *xa)
        }
 }
 
+static noinline void check_xas_get_order(struct xarray *xa)
+{
+       XA_STATE(xas, xa, 0);
+
+       unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
+       unsigned int order;
+       unsigned long i, j;
+
+       for (order = 0; order < max_order; order++) {
+               for (i = 0; i < 10; i++) {
+                       xas_set_order(&xas, i << order, order);
+                       do {
+                               xas_lock(&xas);
+                               xas_store(&xas, xa_mk_value(i));
+                               xas_unlock(&xas);
+                       } while (xas_nomem(&xas, GFP_KERNEL));
+
+                       for (j = i << order; j < (i + 1) << order; j++) {
+                               xas_set_order(&xas, j, 0);
+                               rcu_read_lock();
+                               xas_load(&xas);
+                               XA_BUG_ON(xa, xas_get_order(&xas) != order);
+                               rcu_read_unlock();
+                       }
+
+                       xas_lock(&xas);
+                       xas_set_order(&xas, i << order, order);
+                       xas_store(&xas, NULL);
+                       xas_unlock(&xas);
+               }
+       }
+}
+
 static noinline void check_destroy(struct xarray *xa)
 {
        unsigned long index;
@@ -2035,6 +2068,7 @@ static int xarray_checks(void)
        check_multi_store(&array);
        check_multi_store_advanced(&array);
        check_get_order(&array);
+       check_xas_get_order(&array);
        check_xa_alloc();
        check_find(&array);
        check_find_entry(&array);
index 39f07bfc4dccacd4da23f76bc0c553815728bee5..da79128ad754fccdbef88278cef212fde071f0c7 100644 (file)
@@ -1750,39 +1750,52 @@ unlock:
 EXPORT_SYMBOL(xa_store_range);
 
 /**
- * xa_get_order() - Get the order of an entry.
- * @xa: XArray.
- * @index: Index of the entry.
+ * xas_get_order() - Get the order of an entry.
+ * @xas: XArray operation state.
+ *
+ * Called after xas_load, the xas should not be in an error state.
  *
  * Return: A number between 0 and 63 indicating the order of the entry.
  */
-int xa_get_order(struct xarray *xa, unsigned long index)
+int xas_get_order(struct xa_state *xas)
 {
-       XA_STATE(xas, xa, index);
-       void *entry;
        int order = 0;
 
-       rcu_read_lock();
-       entry = xas_load(&xas);
-
-       if (!entry)
-               goto unlock;
-
-       if (!xas.xa_node)
-               goto unlock;
+       if (!xas->xa_node)
+               return 0;
 
        for (;;) {
-               unsigned int slot = xas.xa_offset + (1 << order);
+               unsigned int slot = xas->xa_offset + (1 << order);
 
                if (slot >= XA_CHUNK_SIZE)
                        break;
-               if (!xa_is_sibling(xas.xa_node->slots[slot]))
+               if (!xa_is_sibling(xa_entry(xas->xa, xas->xa_node, slot)))
                        break;
                order++;
        }
 
-       order += xas.xa_node->shift;
-unlock:
+       order += xas->xa_node->shift;
+       return order;
+}
+EXPORT_SYMBOL_GPL(xas_get_order);
+
+/**
+ * xa_get_order() - Get the order of an entry.
+ * @xa: XArray.
+ * @index: Index of the entry.
+ *
+ * Return: A number between 0 and 63 indicating the order of the entry.
+ */
+int xa_get_order(struct xarray *xa, unsigned long index)
+{
+       XA_STATE(xas, xa, index);
+       int order = 0;
+       void *entry;
+
+       rcu_read_lock();
+       entry = xas_load(&xas);
+       if (entry)
+               order = xas_get_order(&xas);
        rcu_read_unlock();
 
        return order;