aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-12-28 23:20:44 -0500
committerMatthew Wilcox <willy@infradead.org>2019-01-06 22:12:57 -0500
commit76b4e52995654af260f14558e0e07b5b039ae202 (patch)
tree81abacc99a4a81505775c391a8be070925f1c88b /lib/xarray.c
parent4a31896c5b5a2715ecf4033426aa0a35066d92d6 (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.c22
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 */
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
@@ -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;