XArray updates for 5.4
These patches all fix various bugs, some of which people have tripped over and some of which have been caught by automatic tools. Matthew Wilcox (Oracle) (5): XArray: Fix xas_next() with a single entry at 0 idr: Fix idr_get_next_ul race with idr_remove radix tree: Remove radix_tree_iter_find idr: Fix integer overflow in idr_for_each_entry idr: Fix idr_alloc_u32 on 32-bit systems -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEejHryeLBw/spnjHrDpNsjXcpgj4FAl3E4tgACgkQDpNsjXcp gj7YjQf6ArvGGHp3U+w1TRA4KCIrtUdGY4nceDQSYaJ2IVus+fHDQnwMCJb5Rjzw 3aFZKLrrsaWWGKTqqRDKD4zm6I6Mg1239WNCnJ8VQrSRepNQ7WxVXGFn560NDZ5b u7zYXBm3CtlJpkX9JVbokii4LkjuwXzbuSh6cv+X3APBUQ3JXuGBmT7p2PLp0ol9 lNKUrxZCK+CJ7kJo5W81lCzZc6GY2USqwmuqudGACWMm1K24TRL52PeD8NU6IzKc Mw9c7Osa0TlwjSaxObaRgLYzIZQoNbkrMTg0xNr8GZjJIn/yJIxqOBb4k3mZWQF1 5KmLfpLotItt25MP8jxgx+1N03jjvw== =h6eN -----END PGP SIGNATURE----- Merge tag 'xarray-5.4' of git://git.infradead.org/users/willy/linux-dax Pull XArray fixes from Matthew Wilcox: "These all fix various bugs, some of which people have tripped over and some of which have been caught by automatic tools" * tag 'xarray-5.4' of git://git.infradead.org/users/willy/linux-dax: idr: Fix idr_alloc_u32 on 32-bit systems idr: Fix integer overflow in idr_for_each_entry radix tree: Remove radix_tree_iter_find idr: Fix idr_get_next_ul race with idr_remove XArray: Fix xas_next() with a single entry at 0
This commit is contained in:
commit
410ef736a7
|
@ -185,7 +185,7 @@ static inline void idr_preload_end(void)
|
|||
* is convenient for a "not found" value.
|
||||
*/
|
||||
#define idr_for_each_entry(idr, entry, id) \
|
||||
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
|
||||
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; id += 1U)
|
||||
|
||||
/**
|
||||
* idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type.
|
||||
|
|
|
@ -315,24 +315,6 @@ radix_tree_iter_lookup(const struct radix_tree_root *root,
|
|||
return radix_tree_next_chunk(root, iter, RADIX_TREE_ITER_CONTIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* radix_tree_iter_find - find a present entry
|
||||
* @root: radix tree root
|
||||
* @iter: iterator state
|
||||
* @index: start location
|
||||
*
|
||||
* This function returns the slot containing the entry with the lowest index
|
||||
* which is at least @index. If @index is larger than any present entry, this
|
||||
* function returns NULL. The @iter is updated to describe the entry found.
|
||||
*/
|
||||
static inline void __rcu **
|
||||
radix_tree_iter_find(const struct radix_tree_root *root,
|
||||
struct radix_tree_iter *iter, unsigned long index)
|
||||
{
|
||||
radix_tree_iter_init(iter, index);
|
||||
return radix_tree_next_chunk(root, iter, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* radix_tree_iter_retry - retry this chunk of the iteration
|
||||
* @iter: iterator state
|
||||
|
|
31
lib/idr.c
31
lib/idr.c
|
@ -215,7 +215,7 @@ int idr_for_each(const struct idr *idr,
|
|||
EXPORT_SYMBOL(idr_for_each);
|
||||
|
||||
/**
|
||||
* idr_get_next() - Find next populated entry.
|
||||
* idr_get_next_ul() - Find next populated entry.
|
||||
* @idr: IDR handle.
|
||||
* @nextid: Pointer to an ID.
|
||||
*
|
||||
|
@ -224,7 +224,7 @@ EXPORT_SYMBOL(idr_for_each);
|
|||
* to the ID of the found value. To use in a loop, the value pointed to by
|
||||
* nextid must be incremented by the user.
|
||||
*/
|
||||
void *idr_get_next(struct idr *idr, int *nextid)
|
||||
void *idr_get_next_ul(struct idr *idr, unsigned long *nextid)
|
||||
{
|
||||
struct radix_tree_iter iter;
|
||||
void __rcu **slot;
|
||||
|
@ -245,18 +245,14 @@ void *idr_get_next(struct idr *idr, int *nextid)
|
|||
}
|
||||
if (!slot)
|
||||
return NULL;
|
||||
id = iter.index + base;
|
||||
|
||||
if (WARN_ON_ONCE(id > INT_MAX))
|
||||
return NULL;
|
||||
|
||||
*nextid = id;
|
||||
*nextid = iter.index + base;
|
||||
return entry;
|
||||
}
|
||||
EXPORT_SYMBOL(idr_get_next);
|
||||
EXPORT_SYMBOL(idr_get_next_ul);
|
||||
|
||||
/**
|
||||
* idr_get_next_ul() - Find next populated entry.
|
||||
* idr_get_next() - Find next populated entry.
|
||||
* @idr: IDR handle.
|
||||
* @nextid: Pointer to an ID.
|
||||
*
|
||||
|
@ -265,22 +261,17 @@ EXPORT_SYMBOL(idr_get_next);
|
|||
* to the ID of the found value. To use in a loop, the value pointed to by
|
||||
* nextid must be incremented by the user.
|
||||
*/
|
||||
void *idr_get_next_ul(struct idr *idr, unsigned long *nextid)
|
||||
void *idr_get_next(struct idr *idr, int *nextid)
|
||||
{
|
||||
struct radix_tree_iter iter;
|
||||
void __rcu **slot;
|
||||
unsigned long base = idr->idr_base;
|
||||
unsigned long id = *nextid;
|
||||
void *entry = idr_get_next_ul(idr, &id);
|
||||
|
||||
id = (id < base) ? 0 : id - base;
|
||||
slot = radix_tree_iter_find(&idr->idr_rt, &iter, id);
|
||||
if (!slot)
|
||||
if (WARN_ON_ONCE(id > INT_MAX))
|
||||
return NULL;
|
||||
|
||||
*nextid = iter.index + base;
|
||||
return rcu_dereference_raw(*slot);
|
||||
*nextid = id;
|
||||
return entry;
|
||||
}
|
||||
EXPORT_SYMBOL(idr_get_next_ul);
|
||||
EXPORT_SYMBOL(idr_get_next);
|
||||
|
||||
/**
|
||||
* idr_replace() - replace pointer for given ID.
|
||||
|
|
|
@ -1529,7 +1529,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root,
|
|||
offset = radix_tree_find_next_bit(node, IDR_FREE,
|
||||
offset + 1);
|
||||
start = next_index(start, node, offset);
|
||||
if (start > max)
|
||||
if (start > max || start == 0)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
while (offset == RADIX_TREE_MAP_SIZE) {
|
||||
offset = node->offset + 1;
|
||||
|
|
|
@ -1110,6 +1110,28 @@ static noinline void check_find_entry(struct xarray *xa)
|
|||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
}
|
||||
|
||||
static noinline void check_move_tiny(struct xarray *xa)
|
||||
{
|
||||
XA_STATE(xas, xa, 0);
|
||||
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
rcu_read_lock();
|
||||
XA_BUG_ON(xa, xas_next(&xas) != NULL);
|
||||
XA_BUG_ON(xa, xas_next(&xas) != NULL);
|
||||
rcu_read_unlock();
|
||||
xa_store_index(xa, 0, GFP_KERNEL);
|
||||
rcu_read_lock();
|
||||
xas_set(&xas, 0);
|
||||
XA_BUG_ON(xa, xas_next(&xas) != xa_mk_index(0));
|
||||
XA_BUG_ON(xa, xas_next(&xas) != NULL);
|
||||
xas_set(&xas, 0);
|
||||
XA_BUG_ON(xa, xas_prev(&xas) != xa_mk_index(0));
|
||||
XA_BUG_ON(xa, xas_prev(&xas) != NULL);
|
||||
rcu_read_unlock();
|
||||
xa_erase_index(xa, 0);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
}
|
||||
|
||||
static noinline void check_move_small(struct xarray *xa, unsigned long idx)
|
||||
{
|
||||
XA_STATE(xas, xa, 0);
|
||||
|
@ -1217,6 +1239,8 @@ static noinline void check_move(struct xarray *xa)
|
|||
|
||||
xa_destroy(xa);
|
||||
|
||||
check_move_tiny(xa);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
check_move_small(xa, 1UL << i);
|
||||
|
||||
|
|
|
@ -994,6 +994,8 @@ void *__xas_prev(struct xa_state *xas)
|
|||
|
||||
if (!xas_frozen(xas->xa_node))
|
||||
xas->xa_index--;
|
||||
if (!xas->xa_node)
|
||||
return set_bounds(xas);
|
||||
if (xas_not_node(xas->xa_node))
|
||||
return xas_load(xas);
|
||||
|
||||
|
@ -1031,6 +1033,8 @@ void *__xas_next(struct xa_state *xas)
|
|||
|
||||
if (!xas_frozen(xas->xa_node))
|
||||
xas->xa_index++;
|
||||
if (!xas->xa_node)
|
||||
return set_bounds(xas);
|
||||
if (xas_not_node(xas->xa_node))
|
||||
return xas_load(xas);
|
||||
|
||||
|
|
Loading…
Reference in New Issue