]> www.infradead.org Git - users/willy/xarray.git/commitdiff
XArray: Remove xa_reserve & xa_release
authorMatthew Wilcox <willy@infradead.org>
Tue, 12 Mar 2019 18:56:00 +0000 (14:56 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 9 Aug 2019 01:38:19 +0000 (21:38 -0400)
These turned out not to be needed.

Signed-off-by: Matthew Wilcox <willy@infradead.org>
Documentation/core-api/xarray.rst
include/linux/xarray.h
lib/radix-tree.c
lib/test_xarray.c
lib/xarray.c
tools/testing/radix-tree/Makefile

index fcedc5349ace406585db870f87f3fc632a10959a..c1f4a39809dc7fa52893e9c96a3e8d3d4f69141f 100644 (file)
@@ -25,41 +25,36 @@ good performance with large indices.  If your index can be larger than
 ``ULONG_MAX`` then the XArray is not the data type for you.  The most
 important user of the XArray is the page cache.
 
-Each non-``NULL`` entry in the array has three bits associated with
-it called marks.  Each mark may be set or cleared independently of
-the others.  You can iterate over entries which are marked.
-
-Normal pointers may be stored in the XArray directly.  They must be 4-byte
-aligned, which is true for any pointer returned from kmalloc() and
-alloc_page().  It isn't true for arbitrary user-space pointers,
-nor for function pointers.  You can store pointers to statically allocated
-objects, as long as those objects have an alignment of at least 4.
-
-You can also store integers between 0 and ``LONG_MAX`` in the XArray.
-You must first convert it into an entry using xa_mk_value().
-When you retrieve an entry from the XArray, you can check whether it is
-a value entry by calling xa_is_value(), and convert it back to
-an integer by calling xa_to_value().
-
-Some users want to store tagged pointers instead of using the marks
-described above.  They can call xa_tag_pointer() to create an
-entry with a tag, xa_untag_pointer() to turn a tagged entry
-back into an untagged pointer and xa_pointer_tag() to retrieve
-the tag of an entry.  Tagged pointers use the same bits that are used
-to distinguish value entries from normal pointers, so each user must
-decide whether they want to store value entries or tagged pointers in
+Normal pointers may be stored in the XArray directly.  You can also store
+integers between 0 and ``LONG_MAX`` in the XArray.  You must first convert
+integers into an entry using xa_mk_value().  When you retrieve an entry
+from the XArray, you can check whether it is a value entry by calling
+xa_is_value(), and convert it back to an integer by calling xa_to_value().
+
+Some users want to tag the pointers they store in the XArray.  You can
+call xa_tag_pointer() to create an entry with a tag, xa_untag_pointer()
+to turn a tagged entry back into an untagged pointer and xa_pointer_tag()
+to retrieve the tag of an entry.  Tagged pointers use the same bits that
+are used to distinguish value entries from normal pointers, so you must
+decide whether you want to store value entries or tagged pointers in
 any particular XArray.
 
-The XArray does not support storing IS_ERR() pointers as some
-conflict with value entries or internal entries.
+Storing IS_ERR() pointers is not recommended as the values used
+to represent some errors conflict with value entries or internal entries.
 
 An unusual feature of the XArray is the ability to create entries which
 occupy a range of indices.  Once stored to, looking up any index in
 the range will return the same entry as looking up any other index in
 the range.  Setting a mark on one index will set it on all of them.
-Storing to any index will store to all of them.  Multi-index entries can
-be explicitly split into smaller entries, or storing ``NULL`` into any
-entry will cause the XArray to forget about the range.
+Storing to any index will store to all of them.  Multi-index entries
+can be explicitly split into smaller entries, or storing ``NULL`` into
+any entry will cause the XArray to forget about the range.
+
+The XArray supports a reserved entry called ``XA_ZERO_ENTRY``.  This entry
+generally reads back as ``NULL`` and is skipped by iteration, but the
+entry will be seen as occupied.  It does not normally need to be named
+by users of the normal API, but may be needed in some special cases.
+It is exposed through the advanced API.
 
 Normal API
 ==========
@@ -69,29 +64,26 @@ for statically allocated XArrays or xa_init() for dynamically
 allocated ones.  A freshly-initialised XArray contains a ``NULL``
 pointer at every index.
 
-You can then set entries using xa_store() and get entries
-using xa_load().  xa_store will overwrite any entry with the
-new entry and return the previous entry stored at that index.  You can
-use xa_erase() instead of calling xa_store() with a
-``NULL`` entry.  There is no difference between an entry that has never
-been stored to, one that has been erased and one that has most recently
-had ``NULL`` stored to it.
+You can then set entries using xa_store() and get entries using xa_load().
+xa_store overwrites any entry with the new entry and return the previous
+entry stored at that index.  You can use xa_erase() to reset an entry to
+``NULL``.  Calling xa_store() with a ``NULL`` entry is the same
+as calling xa_erase() unless you are using an allocating array
+(see below).
+
+If you want to only store a new entry to an index if the current entry is
+``NULL``, you can use xa_insert() which returns ``-EBUSY`` if the
+entry is not empty.  If you pass ``NULL`` as the entry to be inserted,
+it will instead store a reserved entry.  Attempting to insert an entry over
+a reserved entry will fail.
 
 You can conditionally replace an entry at an index by using
 xa_cmpxchg().  Like cmpxchg(), it will only succeed if
 the entry at that index has the 'old' value.  It also returns the entry
 which was at that index; if it returns the same entry which was passed as
-'old', then xa_cmpxchg() succeeded.
-
-If you want to only store a new entry to an index if the current entry
-at that index is ``NULL``, you can use xa_insert() which
-returns ``-EBUSY`` if the entry is not empty.
-
-You can enquire whether a mark is set on an entry by using
-xa_get_mark().  If the entry is not ``NULL``, you can set a mark
-on it by using xa_set_mark() and remove the mark from an entry by
-calling xa_clear_mark().  You can ask whether any entry in the
-XArray has a particular mark set by calling xa_marked().
+'old', then xa_cmpxchg() succeeded.  Unlike xa_insert(),
+xa_cmpxchg() does not convert either of its arguments from
+``NULL`` to ``XA_ZERO_ENTRY``.
 
 You can copy entries out of the XArray into a plain array by calling
 xa_extract().  Or you can iterate over the present entries in
@@ -106,16 +98,6 @@ may result in the entry being marked at some, but not all of the other
 indices.  Storing into one index may result in the entry retrieved by
 some, but not all of the other indices changing.
 
-Sometimes you need to ensure that a subsequent call to xa_store()
-will not need to allocate memory.  The xa_reserve() function
-will store a reserved entry at the indicated index.  Users of the
-normal API will see this entry as containing ``NULL``.  If you do
-not need to use the reserved entry, you can call xa_release()
-to remove the unused entry.  If another user has stored to the entry
-in the meantime, xa_release() will do nothing; if instead you
-want the entry to become ``NULL``, you should use xa_erase().
-Using xa_insert() on a reserved entry will fail.
-
 If all entries in the array are ``NULL``, the xa_empty() function
 will return ``true``.
 
@@ -124,6 +106,20 @@ xa_destroy().  If the XArray entries are pointers, you may wish
 to free the entries first.  You can do this by iterating over all present
 entries in the XArray using the xa_for_each() iterator.
 
+Search Marks
+------------
+
+Each entry in the array has three bits associated with it called marks.
+Each mark may be set or cleared independently of the others.  You can
+efficiently iterate over all marked entries in the array by using the
+xa_for_each_marked() iterator.
+
+You can enquire whether a mark is set on an entry by using
+xa_get_mark().  If the entry is not ``NULL``, you can set a mark
+on it by using xa_set_mark() and remove the mark from an entry by
+calling xa_clear_mark().  You can ask whether any entry in the
+XArray has a particular mark set by calling xa_marked().
+
 Allocating XArrays
 ------------------
 
@@ -136,11 +132,10 @@ in the XArray.  If you need to modify the array from interrupt context,
 you can use xa_alloc_bh() or xa_alloc_irq() to disable
 interrupts while allocating the ID.
 
-Using xa_store(), xa_cmpxchg() or xa_insert() will
-also mark the entry as being allocated.  Unlike a normal XArray, storing
-``NULL`` will mark the entry as being in use, like xa_reserve().
-To free an entry, use xa_erase() (or xa_release() if
-you only want to free the entry if it's ``NULL``).
+A successful call to xa_store() or xa_insert() will
+also mark the entry as being allocated.  Unlike a normal XArray,
+storing ``NULL`` will store a reserved entry and mark the entry as
+being in use.
 
 By default, the lowest free entry is allocated starting from 0.  If you
 want to allocate entries starting at 1, it is more efficient to use
@@ -155,11 +150,10 @@ available for your use.
 Memory allocation
 -----------------
 
-The xa_store(), xa_cmpxchg(), xa_alloc(),
-xa_reserve() and xa_insert() functions take a gfp_t
-parameter in case the XArray needs to allocate memory to store this entry.
-If the entry is being deleted, no memory allocation needs to be performed,
-and the GFP flags specified will be ignored.
+The xa_store(), xa_cmpxchg(), xa_alloc() and xa_insert() functions take
+a gfp_t parameter in case the XArray needs to allocate memory to store
+this entry.  If the entry is being deleted, no memory allocation needs
+to be performed, and the GFP flags specified will be ignored.
 
 It is possible for no memory to be allocatable, particularly if you pass
 a restrictive set of GFP flags.  In that case, the functions return a
@@ -202,9 +196,6 @@ Takes xa_lock internally:
  * xa_alloc()
  * xa_alloc_bh()
  * xa_alloc_irq()
- * xa_reserve()
- * xa_reserve_bh()
- * xa_reserve_irq()
  * xa_destroy()
  * xa_set_mark()
  * xa_clear_mark()
index 0b53ce49e38b87cc0287fbb79f213ac8d7e67170..9277684b786326ab202811906d09f43ecd644db8 100644 (file)
@@ -714,9 +714,9 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * Inserting a NULL entry will store a reserved entry (like xa_reserve())
- * if no entry is present.  Inserting will fail if a reserved entry is
- * present, even though loading from this index will return NULL.
+ * Inserting a NULL entry will store a reserved entry if no entry is
+ * present.  Inserting will fail if a reserved entry is present, even
+ * though loading from this index will return NULL.
  *
  * Context: Any context.  Takes and releases the xa_lock.  May sleep if
  * the @gfp flags permit.
@@ -743,9 +743,9 @@ static inline int __must_check xa_insert(struct xarray *xa,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * Inserting a NULL entry will store a reserved entry (like xa_reserve())
- * if no entry is present.  Inserting will fail if a reserved entry is
- * present, even though loading from this index will return NULL.
+ * Inserting a NULL entry will store a reserved entry if no entry is
+ * present.  Inserting will fail if a reserved entry is present, even
+ * though loading from this index will return NULL.
  *
  * Context: Any context.  Takes and releases the xa_lock while
  * disabling softirqs.  May sleep if the @gfp flags permit.
@@ -772,9 +772,9 @@ static inline int __must_check xa_insert_bh(struct xarray *xa,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * Inserting a NULL entry will store a reserved entry (like xa_reserve())
- * if no entry is present.  Inserting will fail if a reserved entry is
- * present, even though loading from this index will return NULL.
+ * Inserting a NULL entry will store a reserved entry if no entry is
+ * present.  Inserting will fail if a reserved entry is present, even
+ * though loading from this index will return NULL.
  *
  * Context: Process context.  Takes and releases the xa_lock while
  * disabling interrupts.  May sleep if the @gfp flags permit.
@@ -979,80 +979,6 @@ static inline int xa_alloc_cyclic_irq(struct xarray *xa, u32 *id, void *entry,
        return err;
 }
 
-/**
- * xa_reserve() - Reserve this index in the XArray.
- * @xa: XArray.
- * @index: Index into array.
- * @gfp: Memory allocation flags.
- *
- * Ensures there is somewhere to store an entry at @index in the array.
- * If there is already something stored at @index, this function does
- * nothing.  If there was nothing there, the entry is marked as reserved.
- * Loading from a reserved entry returns a %NULL pointer.
- *
- * If you do not use the entry that you have reserved, call xa_release()
- * or xa_erase() to free any unnecessary memory.
- *
- * Context: Any context.  Takes and releases the xa_lock.
- * May sleep if the @gfp flags permit.
- * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
- */
-static inline __must_check
-int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
-{
-       return xa_err(xa_cmpxchg(xa, index, NULL, XA_ZERO_ENTRY, gfp));
-}
-
-/**
- * xa_reserve_bh() - Reserve this index in the XArray.
- * @xa: XArray.
- * @index: Index into array.
- * @gfp: Memory allocation flags.
- *
- * A softirq-disabling version of xa_reserve().
- *
- * Context: Any context.  Takes and releases the xa_lock while
- * disabling softirqs.
- * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
- */
-static inline __must_check
-int xa_reserve_bh(struct xarray *xa, unsigned long index, gfp_t gfp)
-{
-       return xa_err(xa_cmpxchg_bh(xa, index, NULL, XA_ZERO_ENTRY, gfp));
-}
-
-/**
- * xa_reserve_irq() - Reserve this index in the XArray.
- * @xa: XArray.
- * @index: Index into array.
- * @gfp: Memory allocation flags.
- *
- * An interrupt-disabling version of xa_reserve().
- *
- * Context: Process context.  Takes and releases the xa_lock while
- * disabling interrupts.
- * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
- */
-static inline __must_check
-int xa_reserve_irq(struct xarray *xa, unsigned long index, gfp_t gfp)
-{
-       return xa_err(xa_cmpxchg_irq(xa, index, NULL, XA_ZERO_ENTRY, gfp));
-}
-
-/**
- * xa_release() - Release a reserved entry.
- * @xa: XArray.
- * @index: Index of entry.
- *
- * After calling xa_reserve(), you can call this function to release the
- * reservation.  If the entry at @index has been stored to, this function
- * will do nothing.
- */
-static inline void xa_release(struct xarray *xa, unsigned long index)
-{
-       xa_cmpxchg(xa, index, XA_ZERO_ENTRY, NULL, 0);
-}
-
 /* Everything below here is the Advanced API.  Proceed with caution. */
 
 /*
index 7ee35ba2c858ffe2f1bb47332a5d53faa1b64ba2..6b80e131e8fff087ab311e37e233596faf8111b1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kmemleak.h>
+#include <linux/list.h>
 #include <linux/percpu.h>
 #include <linux/preempt.h>             /* in_interrupt() */
 #include <linux/rcupdate.h>
index 75797cfcf7ca7491ec1b6299f085109069e5903d..9233d5ed27ecaa4e270375376c52a9821969a4be 100644 (file)
@@ -466,29 +466,21 @@ static noinline void check_reserve(struct xarray *xa)
 
        /* An array with a reserved entry is not empty */
        XA_BUG_ON(xa, !xa_empty(xa));
-       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, NULL, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_empty(xa));
        XA_BUG_ON(xa, xa_load(xa, 12345678));
-       xa_release(xa, 12345678);
-       XA_BUG_ON(xa, !xa_empty(xa));
-
-       /* Releasing a used entry does nothing */
-       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
-       XA_BUG_ON(xa, xa_store_index(xa, 12345678, GFP_NOWAIT) != NULL);
-       xa_release(xa, 12345678);
-       xa_erase_index(xa, 12345678);
+       XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* cmpxchg sees a reserved entry as ZERO */
-       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, NULL, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, XA_ZERO_ENTRY,
                                xa_mk_value(12345678), GFP_NOWAIT) != NULL);
-       xa_release(xa, 12345678);
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* xa_insert treats it as busy */
-       XA_BUG_ON(xa, xa_reserve(xa, 12345678, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, NULL, GFP_KERNEL) != 0);
        XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) !=
                        -EBUSY);
        XA_BUG_ON(xa, xa_empty(xa));
@@ -497,7 +489,7 @@ static noinline void check_reserve(struct xarray *xa)
 
        /* Can iterate through a reserved entry */
        xa_store_index(xa, 5, GFP_KERNEL);
-       XA_BUG_ON(xa, xa_reserve(xa, 6, GFP_KERNEL) != 0);
+       XA_BUG_ON(xa, xa_insert(xa, 6, NULL, GFP_KERNEL) != 0);
        xa_store_index(xa, 7, GFP_KERNEL);
 
        count = 0;
@@ -515,7 +507,7 @@ static noinline void check_reserve(struct xarray *xa)
                                        XA_LIMIT(5, 10), GFP_KERNEL) != 0);
                XA_BUG_ON(xa, id != 8);
 
-               xa_release(xa, 6);
+               XA_BUG_ON(xa, xa_erase(xa, 6) != NULL);
                XA_BUG_ON(xa, xa_alloc(xa, &id, xa_mk_value(6),
                                        XA_LIMIT(5, 10), GFP_KERNEL) != 0);
                XA_BUG_ON(xa, id != 6);
@@ -1472,7 +1464,7 @@ static void check_align_2(struct xarray *xa, char *name)
        }
 
        for (i = 0; i < 8; i++) {
-               XA_BUG_ON(xa, xa_reserve(xa, 0, GFP_KERNEL) != 0);
+               XA_BUG_ON(xa, xa_insert(xa, 0, NULL, GFP_KERNEL) != 0);
                XA_BUG_ON(xa, xa_store(xa, 0, name + i, 0) != NULL);
                xa_erase(xa, 0);
        }
index 742d3663b579528da808dc427277474b890cd81f..9cb4f08f95965f25f9c7b957909c766a6ca1b92d 100644 (file)
@@ -1460,9 +1460,9 @@ EXPORT_SYMBOL(__xa_cmpxchg);
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * Inserting a NULL entry will store a reserved entry (like xa_reserve())
- * if no entry is present.  Inserting will fail if a reserved entry is
- * present, even though loading from this index will return NULL.
+ * Inserting a NULL entry will store a reserved entry if no entry is
+ * present.  Inserting will fail if a reserved entry is present, even
+ * though loading from this index will return NULL.
  *
  * Context: Any context.  Expects xa_lock to be held on entry.  May
  * release and reacquire xa_lock if @gfp flags permit.
index b26f0494dc82b0c3859f93289988d84386bb359b..671f225db2d564e7f2dfcc2b56426f43463a1579 100644 (file)
@@ -5,9 +5,10 @@ CFLAGS += -I. -I../../include -g -Og -Wall -D_LGPL_SOURCE -fsanitize=address \
 LDFLAGS += -fsanitize=address -fsanitize=undefined
 LDLIBS+= -lpthread -lurcu
 TARGETS = main idr-test multiorder xarray
-CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o
+CORE_OFILES := xarray.o linux.o radix-tree.o test.o find_bit.o bitmap.o
 OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression4.o \
-        tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o
+        tag_check.o multiorder.o idr.o idr-test.o \
+        iteration_check.o benchmark.o
 
 ifndef SHIFT
        SHIFT=3