Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 410ef736 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 4d8b3262 b7e9728f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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.
+0 −18
Original line number Diff line number Diff line
@@ -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
+11 −20
Original line number Diff line number Diff line
@@ -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.
+1 −1
Original line number Diff line number Diff line
@@ -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;
+24 −0
Original line number Diff line number Diff line
@@ -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);

Loading