lib/xarray.c | 3 +++ 1 file changed, 3 insertions(+)
Suppose xas is pointing somewhere near the end of the multi-entry batch.
Then it may happen that the computed slot already falls beyond the batch,
thus breaking the loop due to !xa_is_sibling(), and computing the wrong
order. For example, suppose we have a shift-6 node having an order-9
entry => 8 - 1 = 7 siblings, so assume the slots are at offset 0 till 7 in
this node. If xas->xa_offset is 6, then the code will compute order as
1 + xas->xa_node->shift = 7. Therefore, the order computation must start
from the beginning of the multi-slot entries, that is, the non-sibling
entry. Thus ensure that the caller is aware of this by triggering a BUG
when the entry is a sibling entry. Note that this BUG_ON() is only
active while running selftests, so there is no overhead in a running
kernel.
Signed-off-by: Dev Jain <dev.jain@arm.com>
---
v1->v2:
- Expand changelog, add comment
Based on Torvalds' master branch.
lib/xarray.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/xarray.c b/lib/xarray.c
index 76dde3a1cacf..ae3d80f4b4ee 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -1910,6 +1910,7 @@ EXPORT_SYMBOL(xa_store_range);
* @xas: XArray operation state.
*
* Called after xas_load, the xas should not be in an error state.
+ * The xas should not be pointing to a sibling entry.
*
* Return: A number between 0 and 63 indicating the order of the entry.
*/
@@ -1920,6 +1921,8 @@ int xas_get_order(struct xa_state *xas)
if (!xas->xa_node)
return 0;
+ XA_NODE_BUG_ON(xas->xa_node, xa_is_sibling(xa_entry(xas->xa,
+ xas->xa_node, xas->xa_offset)));
for (;;) {
unsigned int slot = xas->xa_offset + (1 << order);
--
2.30.2
On 04/06/25 9:45 am, Dev Jain wrote: > Suppose xas is pointing somewhere near the end of the multi-entry batch. > Then it may happen that the computed slot already falls beyond the batch, > thus breaking the loop due to !xa_is_sibling(), and computing the wrong > order. For example, suppose we have a shift-6 node having an order-9 > entry => 8 - 1 = 7 siblings, so assume the slots are at offset 0 till 7 in > this node. If xas->xa_offset is 6, then the code will compute order as > 1 + xas->xa_node->shift = 7. Therefore, the order computation must start > from the beginning of the multi-slot entries, that is, the non-sibling > entry. Thus ensure that the caller is aware of this by triggering a BUG > when the entry is a sibling entry. Note that this BUG_ON() is only > active while running selftests, so there is no overhead in a running > kernel. > > Signed-off-by: Dev Jain <dev.jain@arm.com> > --- Gentle ping, is anything else required from my side.
On 4 Jun 2025, at 0:15, Dev Jain wrote: > Suppose xas is pointing somewhere near the end of the multi-entry batch. > Then it may happen that the computed slot already falls beyond the batch, > thus breaking the loop due to !xa_is_sibling(), and computing the wrong > order. For example, suppose we have a shift-6 node having an order-9 > entry => 8 - 1 = 7 siblings, so assume the slots are at offset 0 till 7 in > this node. If xas->xa_offset is 6, then the code will compute order as > 1 + xas->xa_node->shift = 7. Therefore, the order computation must start > from the beginning of the multi-slot entries, that is, the non-sibling > entry. Thus ensure that the caller is aware of this by triggering a BUG > when the entry is a sibling entry. Note that this BUG_ON() is only > active while running selftests, so there is no overhead in a running > kernel. > > Signed-off-by: Dev Jain <dev.jain@arm.com> > --- > v1->v2: > - Expand changelog, add comment > > Based on Torvalds' master branch. > > lib/xarray.c | 3 +++ > 1 file changed, 3 insertions(+) > The added comment is also clarifying the function requirement. Thanks. Acked-by: Zi Yan <ziy@nvidia.com> -- Best Regards, Yan, Zi
On Wed, 4 Jun 2025 09:45:33 +0530 Dev Jain <dev.jain@arm.com> wrote: > Suppose xas is pointing somewhere near the end of the multi-entry batch. > Then it may happen that the computed slot already falls beyond the batch, > thus breaking the loop due to !xa_is_sibling(), and computing the wrong > order. For example, suppose we have a shift-6 node having an order-9 > entry => 8 - 1 = 7 siblings, so assume the slots are at offset 0 till 7 in > this node. If xas->xa_offset is 6, then the code will compute order as > 1 + xas->xa_node->shift = 7. Therefore, the order computation must start > from the beginning of the multi-slot entries, that is, the non-sibling > entry. Thus ensure that the caller is aware of this by triggering a BUG > when the entry is a sibling entry. Why check this thing in particular? There are a zillion things we could check... > Note that this BUG_ON() is only > active while running selftests, so there is no overhead in a running > kernel. hm, how do we know this? Now and in the future? xa_get_order() and xas_get_order() have callers all over the place.
On 04/06/25 10:03 am, Andrew Morton wrote: > On Wed, 4 Jun 2025 09:45:33 +0530 Dev Jain <dev.jain@arm.com> wrote: > >> Suppose xas is pointing somewhere near the end of the multi-entry batch. >> Then it may happen that the computed slot already falls beyond the batch, >> thus breaking the loop due to !xa_is_sibling(), and computing the wrong >> order. For example, suppose we have a shift-6 node having an order-9 >> entry => 8 - 1 = 7 siblings, so assume the slots are at offset 0 till 7 in >> this node. If xas->xa_offset is 6, then the code will compute order as >> 1 + xas->xa_node->shift = 7. Therefore, the order computation must start >> from the beginning of the multi-slot entries, that is, the non-sibling >> entry. Thus ensure that the caller is aware of this by triggering a BUG >> when the entry is a sibling entry. > Why check this thing in particular? There are a zillion things we > could check... Well, it jumped out to me while reading code. If the concensus is that a BUG_ON() is totally unnecessary, I will at least prefer a comment. I just thought that there are XA_NODE_BUG_ON()'s all over the place, and they must be there for some good reason, so let's follow that. >> Note that this BUG_ON() is only >> active while running selftests, so there is no overhead in a running >> kernel. > hm, how do we know this? Now and in the future? xa_get_order() and > xas_get_order() have callers all over the place. XA_NODE_BUG_ON() depends on #ifdef XA_DEBUG(), which is defined in a tools/testing directory...and in the future if this changes then I think that work will include removing all XA_NODE_BUG_ON()'s... >
© 2016 - 2025 Red Hat, Inc.