aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c92
1 files changed, 54 insertions, 38 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index 5f3f9311de89..81c3171ddde9 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -232,6 +232,8 @@ void *xas_load(struct xa_state *xas)
232 if (xas->xa_shift > node->shift) 232 if (xas->xa_shift > node->shift)
233 break; 233 break;
234 entry = xas_descend(xas, node); 234 entry = xas_descend(xas, node);
235 if (node->shift == 0)
236 break;
235 } 237 }
236 return entry; 238 return entry;
237} 239}
@@ -506,7 +508,7 @@ static void xas_free_nodes(struct xa_state *xas, struct xa_node *top)
506 for (;;) { 508 for (;;) {
507 void *entry = xa_entry_locked(xas->xa, node, offset); 509 void *entry = xa_entry_locked(xas->xa, node, offset);
508 510
509 if (xa_is_node(entry)) { 511 if (node->shift && xa_is_node(entry)) {
510 node = xa_to_node(entry); 512 node = xa_to_node(entry);
511 offset = 0; 513 offset = 0;
512 continue; 514 continue;
@@ -604,6 +606,7 @@ static int xas_expand(struct xa_state *xas, void *head)
604/* 606/*
605 * xas_create() - Create a slot to store an entry in. 607 * xas_create() - Create a slot to store an entry in.
606 * @xas: XArray operation state. 608 * @xas: XArray operation state.
609 * @allow_root: %true if we can store the entry in the root directly
607 * 610 *
608 * Most users will not need to call this function directly, as it is called 611 * Most users will not need to call this function directly, as it is called
609 * by xas_store(). It is useful for doing conditional store operations 612 * by xas_store(). It is useful for doing conditional store operations
@@ -613,7 +616,7 @@ static int xas_expand(struct xa_state *xas, void *head)
613 * If the slot was newly created, returns %NULL. If it failed to create the 616 * If the slot was newly created, returns %NULL. If it failed to create the
614 * slot, returns %NULL and indicates the error in @xas. 617 * slot, returns %NULL and indicates the error in @xas.
615 */ 618 */
616static void *xas_create(struct xa_state *xas) 619static void *xas_create(struct xa_state *xas, bool allow_root)
617{ 620{
618 struct xarray *xa = xas->xa; 621 struct xarray *xa = xas->xa;
619 void *entry; 622 void *entry;
@@ -628,6 +631,8 @@ static void *xas_create(struct xa_state *xas)
628 shift = xas_expand(xas, entry); 631 shift = xas_expand(xas, entry);
629 if (shift < 0) 632 if (shift < 0)
630 return NULL; 633 return NULL;
634 if (!shift && !allow_root)
635 shift = XA_CHUNK_SHIFT;
631 entry = xa_head_locked(xa); 636 entry = xa_head_locked(xa);
632 slot = &xa->xa_head; 637 slot = &xa->xa_head;
633 } else if (xas_error(xas)) { 638 } else if (xas_error(xas)) {
@@ -687,7 +692,7 @@ void xas_create_range(struct xa_state *xas)
687 xas->xa_sibs = 0; 692 xas->xa_sibs = 0;
688 693
689 for (;;) { 694 for (;;) {
690 xas_create(xas); 695 xas_create(xas, true);
691 if (xas_error(xas)) 696 if (xas_error(xas))
692 goto restore; 697 goto restore;
693 if (xas->xa_index <= (index | XA_CHUNK_MASK)) 698 if (xas->xa_index <= (index | XA_CHUNK_MASK))
@@ -754,7 +759,7 @@ void *xas_store(struct xa_state *xas, void *entry)
754 bool value = xa_is_value(entry); 759 bool value = xa_is_value(entry);
755 760
756 if (entry) 761 if (entry)
757 first = xas_create(xas); 762 first = xas_create(xas, !xa_is_node(entry));
758 else 763 else
759 first = xas_load(xas); 764 first = xas_load(xas);
760 765
@@ -1251,35 +1256,6 @@ void *xas_find_conflict(struct xa_state *xas)
1251EXPORT_SYMBOL_GPL(xas_find_conflict); 1256EXPORT_SYMBOL_GPL(xas_find_conflict);
1252 1257
1253/** 1258/**
1254 * xa_init_flags() - Initialise an empty XArray with flags.
1255 * @xa: XArray.
1256 * @flags: XA_FLAG values.
1257 *
1258 * If you need to initialise an XArray with special flags (eg you need
1259 * to take the lock from interrupt context), use this function instead
1260 * of xa_init().
1261 *
1262 * Context: Any context.
1263 */
1264void xa_init_flags(struct xarray *xa, gfp_t flags)
1265{
1266 unsigned int lock_type;
1267 static struct lock_class_key xa_lock_irq;
1268 static struct lock_class_key xa_lock_bh;
1269
1270 spin_lock_init(&xa->xa_lock);
1271 xa->xa_flags = flags;
1272 xa->xa_head = NULL;
1273
1274 lock_type = xa_lock_type(xa);
1275 if (lock_type == XA_LOCK_IRQ)
1276 lockdep_set_class(&xa->xa_lock, &xa_lock_irq);
1277 else if (lock_type == XA_LOCK_BH)
1278 lockdep_set_class(&xa->xa_lock, &xa_lock_bh);
1279}
1280EXPORT_SYMBOL(xa_init_flags);
1281
1282/**
1283 * xa_load() - Load an entry from an XArray. 1259 * xa_load() - Load an entry from an XArray.
1284 * @xa: XArray. 1260 * @xa: XArray.
1285 * @index: index into array. 1261 * @index: index into array.
@@ -1308,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr)
1308{ 1284{
1309 if (xa_is_zero(curr)) 1285 if (xa_is_zero(curr))
1310 return NULL; 1286 return NULL;
1311 XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
1312 if (xas_error(xas)) 1287 if (xas_error(xas))
1313 curr = xas->xa_node; 1288 curr = xas->xa_node;
1314 return curr; 1289 return curr;
@@ -1378,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1378 XA_STATE(xas, xa, index); 1353 XA_STATE(xas, xa, index);
1379 void *curr; 1354 void *curr;
1380 1355
1381 if (WARN_ON_ONCE(xa_is_internal(entry))) 1356 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1382 return XA_ERROR(-EINVAL); 1357 return XA_ERROR(-EINVAL);
1383 if (xa_track_free(xa) && !entry) 1358 if (xa_track_free(xa) && !entry)
1384 entry = XA_ZERO_ENTRY; 1359 entry = XA_ZERO_ENTRY;
@@ -1444,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1444 XA_STATE(xas, xa, index); 1419 XA_STATE(xas, xa, index);
1445 void *curr; 1420 void *curr;
1446 1421
1447 if (WARN_ON_ONCE(xa_is_internal(entry))) 1422 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1448 return XA_ERROR(-EINVAL); 1423 return XA_ERROR(-EINVAL);
1449 if (xa_track_free(xa) && !entry) 1424 if (xa_track_free(xa) && !entry)
1450 entry = XA_ZERO_ENTRY; 1425 entry = XA_ZERO_ENTRY;
@@ -1465,6 +1440,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1465EXPORT_SYMBOL(__xa_cmpxchg); 1440EXPORT_SYMBOL(__xa_cmpxchg);
1466 1441
1467/** 1442/**
1443 * __xa_insert() - Store this entry in the XArray if no entry is present.
1444 * @xa: XArray.
1445 * @index: Index into array.
1446 * @entry: New entry.
1447 * @gfp: Memory allocation flags.
1448 *
1449 * Inserting a NULL entry will store a reserved entry (like xa_reserve())
1450 * if no entry is present. Inserting will fail if a reserved entry is
1451 * present, even though loading from this index will return NULL.
1452 *
1453 * Context: Any context. Expects xa_lock to be held on entry. May
1454 * release and reacquire xa_lock if @gfp flags permit.
1455 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
1456 * -ENOMEM if memory could not be allocated.
1457 */
1458int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1459{
1460 XA_STATE(xas, xa, index);
1461 void *curr;
1462
1463 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1464 return -EINVAL;
1465 if (!entry)
1466 entry = XA_ZERO_ENTRY;
1467
1468 do {
1469 curr = xas_load(&xas);
1470 if (!curr) {
1471 xas_store(&xas, entry);
1472 if (xa_track_free(xa))
1473 xas_clear_mark(&xas, XA_FREE_MARK);
1474 } else {
1475 xas_set_err(&xas, -EEXIST);
1476 }
1477 } while (__xas_nomem(&xas, gfp));
1478
1479 return xas_error(&xas);
1480}
1481EXPORT_SYMBOL(__xa_insert);
1482
1483/**
1468 * __xa_reserve() - Reserve this index in the XArray. 1484 * __xa_reserve() - Reserve this index in the XArray.
1469 * @xa: XArray. 1485 * @xa: XArray.
1470 * @index: Index into array. 1486 * @index: Index into array.
@@ -1567,7 +1583,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first,
1567 if (last + 1) 1583 if (last + 1)
1568 order = __ffs(last + 1); 1584 order = __ffs(last + 1);
1569 xas_set_order(&xas, last, order); 1585 xas_set_order(&xas, last, order);
1570 xas_create(&xas); 1586 xas_create(&xas, true);
1571 if (xas_error(&xas)) 1587 if (xas_error(&xas))
1572 goto unlock; 1588 goto unlock;
1573 } 1589 }
@@ -1609,7 +1625,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
1609 XA_STATE(xas, xa, 0); 1625 XA_STATE(xas, xa, 0);
1610 int err; 1626 int err;
1611 1627
1612 if (WARN_ON_ONCE(xa_is_internal(entry))) 1628 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1613 return -EINVAL; 1629 return -EINVAL;
1614 if (WARN_ON_ONCE(!xa_track_free(xa))) 1630 if (WARN_ON_ONCE(!xa_track_free(xa)))
1615 return -EINVAL; 1631 return -EINVAL;