diff options
author | Matthew Wilcox <willy@infradead.org> | 2019-01-02 13:57:03 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2019-01-06 22:12:58 -0500 |
commit | b0606fed6eece16a421034eca0bbea9a08b90e91 (patch) | |
tree | f705b58760a60fce2d6f03a934a5038154505c1b /lib/xarray.c | |
parent | 76b4e52995654af260f14558e0e07b5b039ae202 (diff) |
XArray: Honour reserved entries in xa_insert
xa_insert() should treat reserved entries as occupied, not as available.
Also, it should treat requests to insert a NULL pointer as a request
to reserve the slot. Add xa_insert_bh() and xa_insert_irq() for
completeness.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index bffa26b1f0d6..81c3171ddde9 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -1440,6 +1440,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1440 | EXPORT_SYMBOL(__xa_cmpxchg); | 1440 | EXPORT_SYMBOL(__xa_cmpxchg); |
1441 | 1441 | ||
1442 | /** | 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 | */ | ||
1458 | int __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 | } | ||
1481 | EXPORT_SYMBOL(__xa_insert); | ||
1482 | |||
1483 | /** | ||
1443 | * __xa_reserve() - Reserve this index in the XArray. | 1484 | * __xa_reserve() - Reserve this index in the XArray. |
1444 | * @xa: XArray. | 1485 | * @xa: XArray. |
1445 | * @index: Index into array. | 1486 | * @index: Index into array. |