diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-12-28 23:20:44 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2019-01-06 22:12:57 -0500 |
commit | 76b4e52995654af260f14558e0e07b5b039ae202 (patch) | |
tree | 81abacc99a4a81505775c391a8be070925f1c88b /lib/xarray.c | |
parent | 4a31896c5b5a2715ecf4033426aa0a35066d92d6 (diff) |
XArray: Permit storing 2-byte-aligned pointers
On m68k, statically allocated pointers may only be two-byte aligned.
This clashes with the XArray's method for tagging internal pointers.
Permit storing these pointers in single slots (ie not in multislots).
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index dda6026d202e..bffa26b1f0d6 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 | */ |
616 | static void *xas_create(struct xa_state *xas) | 619 | static 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 | ||
@@ -1279,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr) | |||
1279 | { | 1284 | { |
1280 | if (xa_is_zero(curr)) | 1285 | if (xa_is_zero(curr)) |
1281 | return NULL; | 1286 | return NULL; |
1282 | XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr)); | ||
1283 | if (xas_error(xas)) | 1287 | if (xas_error(xas)) |
1284 | curr = xas->xa_node; | 1288 | curr = xas->xa_node; |
1285 | return curr; | 1289 | return curr; |
@@ -1349,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | |||
1349 | XA_STATE(xas, xa, index); | 1353 | XA_STATE(xas, xa, index); |
1350 | void *curr; | 1354 | void *curr; |
1351 | 1355 | ||
1352 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1356 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1353 | return XA_ERROR(-EINVAL); | 1357 | return XA_ERROR(-EINVAL); |
1354 | if (xa_track_free(xa) && !entry) | 1358 | if (xa_track_free(xa) && !entry) |
1355 | entry = XA_ZERO_ENTRY; | 1359 | entry = XA_ZERO_ENTRY; |
@@ -1415,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1415 | XA_STATE(xas, xa, index); | 1419 | XA_STATE(xas, xa, index); |
1416 | void *curr; | 1420 | void *curr; |
1417 | 1421 | ||
1418 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1422 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1419 | return XA_ERROR(-EINVAL); | 1423 | return XA_ERROR(-EINVAL); |
1420 | if (xa_track_free(xa) && !entry) | 1424 | if (xa_track_free(xa) && !entry) |
1421 | entry = XA_ZERO_ENTRY; | 1425 | entry = XA_ZERO_ENTRY; |
@@ -1538,7 +1542,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first, | |||
1538 | if (last + 1) | 1542 | if (last + 1) |
1539 | order = __ffs(last + 1); | 1543 | order = __ffs(last + 1); |
1540 | xas_set_order(&xas, last, order); | 1544 | xas_set_order(&xas, last, order); |
1541 | xas_create(&xas); | 1545 | xas_create(&xas, true); |
1542 | if (xas_error(&xas)) | 1546 | if (xas_error(&xas)) |
1543 | goto unlock; | 1547 | goto unlock; |
1544 | } | 1548 | } |
@@ -1580,7 +1584,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp) | |||
1580 | XA_STATE(xas, xa, 0); | 1584 | XA_STATE(xas, xa, 0); |
1581 | int err; | 1585 | int err; |
1582 | 1586 | ||
1583 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1587 | if (WARN_ON_ONCE(xa_is_advanced(entry))) |
1584 | return -EINVAL; | 1588 | return -EINVAL; |
1585 | if (WARN_ON_ONCE(!xa_track_free(xa))) | 1589 | if (WARN_ON_ONCE(!xa_track_free(xa))) |
1586 | return -EINVAL; | 1590 | return -EINVAL; |