Commit d7727819 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

devlink: bump the instance index directly when iterating



xa_find_after() is designed to handle multi-index entries correctly.
If a xarray has two entries one which spans indexes 0-3 and one at
index 4 xa_find_after(0) will return the entry at index 4.

Having to juggle the two callbacks, however, is unnecessary in case
of the devlink xarray, as there is 1:1 relationship with indexes.

Always use xa_find() and increment the index manually.

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6b754d7b
Loading
Loading
Loading
Loading
+9 −22
Original line number Diff line number Diff line
@@ -91,16 +91,13 @@ void devlink_put(struct devlink *devlink)
		call_rcu(&devlink->rcu, __devlink_put_rcu);
}

struct devlink *
devlinks_xa_find_get(struct net *net, unsigned long *indexp,
		     void * (*xa_find_fn)(struct xarray *, unsigned long *,
					  unsigned long, xa_mark_t))
struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
{
	struct devlink *devlink;
	struct devlink *devlink = NULL;

	rcu_read_lock();
retry:
	devlink = xa_find_fn(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
	devlink = xa_find(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
	if (!devlink)
		goto unlock;

@@ -109,31 +106,21 @@ devlinks_xa_find_get(struct net *net, unsigned long *indexp,
	 * This prevents live-lock of devlink_unregister() wait for completion.
	 */
	if (xa_get_mark(&devlinks, *indexp, DEVLINK_UNREGISTERING))
		goto retry;
		goto next;

	/* For a possible retry, the xa_find_after() should be always used */
	xa_find_fn = xa_find_after;
	if (!devlink_try_get(devlink))
		goto retry;
		goto next;
	if (!net_eq(devlink_net(devlink), net)) {
		devlink_put(devlink);
		goto retry;
		goto next;
	}
unlock:
	rcu_read_unlock();
	return devlink;
}

struct devlink *
devlinks_xa_find_get_first(struct net *net, unsigned long *indexp)
{
	return devlinks_xa_find_get(net, indexp, xa_find);
}

struct devlink *
devlinks_xa_find_get_next(struct net *net, unsigned long *indexp)
{
	return devlinks_xa_find_get(net, indexp, xa_find_after);
next:
	(*indexp)++;
	goto retry;
}

/**
+4 −13
Original line number Diff line number Diff line
@@ -82,18 +82,9 @@ extern struct genl_family devlink_nl_family;
 * in loop body in order to release the reference.
 */
#define devlinks_xa_for_each_registered_get(net, index, devlink)	\
	for (index = 0,							\
	     devlink = devlinks_xa_find_get_first(net, &index);	\
	     devlink; devlink = devlinks_xa_find_get_next(net, &index))

struct devlink *
devlinks_xa_find_get(struct net *net, unsigned long *indexp,
		     void * (*xa_find_fn)(struct xarray *, unsigned long *,
					  unsigned long, xa_mark_t));
struct devlink *
devlinks_xa_find_get_first(struct net *net, unsigned long *indexp);
struct devlink *
devlinks_xa_find_get_next(struct net *net, unsigned long *indexp);
	for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)

struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);

/* Netlink */
#define DEVLINK_NL_FLAG_NEED_PORT		BIT(0)
@@ -135,7 +126,7 @@ struct devlink_gen_cmd {
 */
#define devlink_dump_for_each_instance_get(msg, state, devlink)		\
	for (; (devlink = devlinks_xa_find_get(sock_net(msg->sk),	\
					       &state->instance, xa_find)); \
					       &state->instance));	\
	     state->instance++, state->idx = 0)

extern const struct genl_small_ops devlink_nl_ops[56];