summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-10-01 14:54:59 -0400
committerMatthew Wilcox <willy@infradead.org>2018-10-21 10:46:00 -0400
commit9f14d4f1f1045f161fd4db8a8e194b7825c2874a (patch)
treefcc3e832d34116dec5dfe2e36525cbdb81cc47c8 /include/linux
parent2264f5132fe45571139727ebdeb78696b35d1506 (diff)
xarray: Add xa_reserve and xa_release
This function reserves a slot in the XArray for users which need to acquire multiple locks before storing their entry in the tree and so cannot use a plain xa_store(). Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/xarray.h34
1 files changed, 32 insertions, 2 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h
index deae17aa0ed7..bed63d3cfea8 100644
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -32,7 +32,8 @@
* The following internal entries have a special meaning:
*
* 0-62: Sibling entries
- * 256: Retry entry
+ * 256: Zero entry
+ * 257: Retry entry
*
* Errors are also represented as internal entries, but use the negative
* space (-4094 to -2). They're never stored in the slots array; only
@@ -277,6 +278,7 @@ void *xa_load(struct xarray *, unsigned long index);
void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
void *xa_cmpxchg(struct xarray *, unsigned long index,
void *old, void *entry, gfp_t);
+int xa_reserve(struct xarray *, unsigned long index, gfp_t);
bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
void xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
void xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
@@ -372,6 +374,20 @@ static inline int xa_insert(struct xarray *xa, unsigned long index,
}
/**
+ * 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, NULL, NULL, 0);
+}
+
+/**
* xa_for_each() - Iterate over a portion of an XArray.
* @xa: XArray.
* @entry: Entry retrieved from array.
@@ -658,7 +674,19 @@ static inline bool xa_is_sibling(const void *entry)
(entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));
}
-#define XA_RETRY_ENTRY xa_mk_internal(256)
+#define XA_ZERO_ENTRY xa_mk_internal(256)
+#define XA_RETRY_ENTRY xa_mk_internal(257)
+
+/**
+ * xa_is_zero() - Is the entry a zero entry?
+ * @entry: Entry retrieved from the XArray
+ *
+ * Return: %true if the entry is a zero entry.
+ */
+static inline bool xa_is_zero(const void *entry)
+{
+ return unlikely(entry == XA_ZERO_ENTRY);
+}
/**
* xa_is_retry() - Is the entry a retry entry?
@@ -880,6 +908,8 @@ static inline void xas_reset(struct xa_state *xas)
*/
static inline bool xas_retry(struct xa_state *xas, const void *entry)
{
+ if (xa_is_zero(entry))
+ return true;
if (!xa_is_retry(entry))
return false;
xas_reset(xas);