History

xarray: Track free entries in an XArray

Add the optional ability to track which entries in an XArray are free and provide xa_alloc() to replace most of the functionality of the IDR.

Matthew Wilcox committed 8 years ago

Commit 371c7521 parent 3d5bd6e4 files · +266 −7Browse files

Showing the changes to lib/xarray.c (1 of 4 files). Show all

Unified · Split

lib/xarray.c+84−4
@@ -52,6 +52,11 @@ static inline void xas_unlock_type(struct xa_state *xas, unsigned int lock_type) · 51 unmodified lines
5252 xas_unlock(xas);
5353 }
5454
55+static inline bool xa_track_free(const struct xarray *xa)
56+{
57+ return xa->xa_flags & XA_FLAGS_TRACK_FREE;
58+}
59+
5560 static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark)
5661 {
5762 if (!(xa->xa_flags & XA_FLAGS_MARK(mark)))
@@ -94,6 +99,11 @@ static inline bool node_any_mark(struct xa_node *node, xa_mark_t mark) · 36 unmodified lines
9499 return !bitmap_empty(node_marks(node, mark), XA_CHUNK_SIZE);
95100 }
96101
102+static inline void node_mark_all(struct xa_node *node, xa_mark_t mark)
103+{
104+ bitmap_fill(node_marks(node, mark), XA_CHUNK_SIZE);
105+}
106+
97107 #define mark_inc(mark) do { \
98108 mark = (__force xa_mark_t)((__force unsigned)(mark) + 1); \
99109 } while (0)
@@ -416,6 +426,8 @@ static void xas_shrink(struct xa_state *xas) · 316 unmodified lines
416426 xas->xa_node = XAS_BOUNDS;
417427
418428 RCU_INIT_POINTER(xa->xa_head, entry);
429+ if (xa_track_free(xa) && !node_get_mark(node, 0, XA_FREE_MARK))
430+ xa_mark_clear(xa, XA_FREE_MARK);
419431
420432 node->count = 0;
421433 node->nr_values = 0;
@@ -549,8 +561,15 @@ static int xas_expand(struct xa_state *xas, void *head) · 127 unmodified lines
549561
550562 /* Propagate the aggregated mark info to the new child */
551563 for (;;) {
552− if (xa_marked(xa, mark))
564+ if (xa_track_free(xa) && mark == XA_FREE_MARK) {
565+ node_mark_all(node, XA_FREE_MARK);
566+ if (!xa_marked(xa, XA_FREE_MARK)) {
567+ node_clear_mark(node, 0, XA_FREE_MARK);
568+ xa_mark_set(xa, XA_FREE_MARK);
569+ }
570+ } else if (xa_marked(xa, mark)) {
553571 node_set_mark(node, 0, mark);
572+ }
554573 if (mark == XA_MARK_MAX)
555574 break;
556575 mark_inc(mark);
@@ -624,6 +643,8 @@ static void *xas_create(struct xa_state *xas) · 67 unmodified lines
624643 node = xas_alloc(xas, shift);
625644 if (!node)
626645 break;
646+ if (xa_track_free(xa))
647+ node_mark_all(node, XA_FREE_MARK);
627648 rcu_assign_pointer(*slot, xa_mk_node(node));
628649 } else if (xa_is_node(entry)) {
629650 node = xa_to_node(entry);
@@ -882,7 +903,10 @@ void xas_init_marks(const struct xa_state *xas) · 252 unmodified lines
882903 xa_mark_t mark = 0;
883904
884905 for (;;) {
885− xas_clear_mark(xas, mark);
906+ if (xa_track_free(xas->xa) && mark == XA_FREE_MARK)
907+ xas_set_mark(xas, mark);
908+ else
909+ xas_clear_mark(xas, mark);
886910 if (mark == XA_MARK_MAX)
887911 break;
888912 mark_inc(mark);
@@ -1333,6 +1357,8 @@ void *xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) · 444 unmodified lines
13331357 do {
13341358 xas_lock(&xas);
13351359 curr = xas_store(&xas, entry);
1360+ if (xa_track_free(xa) && entry)
1361+ xas_clear_mark(&xas, XA_FREE_MARK);
13361362 xas_unlock(&xas);
13371363 } while (xas_nomem(&xas, gfp));
13381364
@@ -1365,6 +1391,8 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) · 26 unmodified lines
13651391
13661392 do {
13671393 curr = xas_store(&xas, entry);
1394+ if (xa_track_free(xa) && entry)
1395+ xas_clear_mark(&xas, XA_FREE_MARK);
13681396 } while (__xas_nomem(&xas, gfp));
13691397
13701398 return xas_result(&xas, curr);
@@ -1400,8 +1428,11 @@ void *xa_cmpxchg(struct xarray *xa, unsigned long index, · 29 unmodified lines
14001428 curr = xas_load(&xas);
14011429 if (curr == XA_ZERO_ENTRY)
14021430 curr = NULL;
1403− if (curr == old)
1431+ if (curr == old) {
14041432 xas_store(&xas, entry);
1433+ if (xa_track_free(xa) && entry)
1434+ xas_clear_mark(&xas, XA_FREE_MARK);
1435+ }
14051436 xas_unlock(&xas);
14061437 } while (xas_nomem(&xas, gfp));
14071438
@@ -1438,8 +1469,11 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, · 30 unmodified lines
14381469 curr = xas_load(&xas);
14391470 if (curr == XA_ZERO_ENTRY)
14401471 curr = NULL;
1441− if (curr == old)
1472+ if (curr == old) {
14421473 xas_store(&xas, entry);
1474+ if (xa_track_free(xa) && entry)
1475+ xas_clear_mark(&xas, XA_FREE_MARK);
1476+ }
14431477 } while (__xas_nomem(&xas, gfp));
14441478
14451479 return xas_result(&xas, curr);
@@ -1483,6 +1517,52 @@ int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp) · 37 unmodified lines
14831517 }
14841518 EXPORT_SYMBOL(xa_reserve);
14851519
1520+/**
1521+ * __xa_alloc() - Find somewhere to store this entry in the XArray.
1522+ * @xa: XArray.
1523+ * @id: Pointer to ID.
1524+ * @max: Maximum ID to allocate (inclusive).
1525+ * @entry: New entry.
1526+ * @gfp: Memory allocation flags.
1527+ *
1528+ * Allocates an unused ID in the range specified by @id and @max.
1529+ * Updates the @id pointer with the index, then stores the entry at that
1530+ * index. A concurrent lookup will not see an uninitialised @id.
1531+ *
1532+ * Context: Any context. Expects xa_lock to be held on entry. May
1533+ * release and reacquire xa_lock if @gfp flags permit.
1534+ * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if
1535+ * there is no more space in the XArray.
1536+ */
1537+int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
1538+{
1539+ XA_STATE(xas, xa, 0);
1540+ int err;
1541+
1542+ if (WARN_ON_ONCE(xa_is_internal(entry)))
1543+ return -EINVAL;
1544+ if (WARN_ON_ONCE(!xa_track_free(xa)))
1545+ return -EINVAL;
1546+
1547+ if (!entry)
1548+ entry = XA_ZERO_ENTRY;
1549+
1550+ do {
1551+ xas.xa_index = *id;
1552+ xas_find_marked(&xas, max, XA_FREE_MARK);
1553+ if (xas.xa_node == XAS_RESTART)
1554+ xas_set_err(&xas, -ENOSPC);
1555+ xas_store(&xas, entry);
1556+ xas_clear_mark(&xas, XA_FREE_MARK);
1557+ } while (__xas_nomem(&xas, gfp));
1558+
1559+ err = xas_error(&xas);
1560+ if (!err)
1561+ *id = xas.xa_index;
1562+ return err;
1563+}
1564+EXPORT_SYMBOL(__xa_alloc);
1565+
14861566 /**
14871567 * __xa_set_mark() - Set this mark on this entry while locked.
14881568 * @xa: XArray.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t