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:
Linus Torvalds 2019-11-08 08:46:49 -08:00
commit 410ef736a7
6 changed files with 41 additions and 40 deletions

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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);