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

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
...@@ -91,16 +91,13 @@ void devlink_put(struct devlink *devlink) ...@@ -91,16 +91,13 @@ void devlink_put(struct devlink *devlink)
call_rcu(&devlink->rcu, __devlink_put_rcu); call_rcu(&devlink->rcu, __devlink_put_rcu);
} }
struct devlink * struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp)
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 *devlink; struct devlink *devlink = NULL;
rcu_read_lock(); rcu_read_lock();
retry: retry:
devlink = xa_find_fn(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED); devlink = xa_find(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED);
if (!devlink) if (!devlink)
goto unlock; goto unlock;
...@@ -109,31 +106,21 @@ devlinks_xa_find_get(struct net *net, unsigned long *indexp, ...@@ -109,31 +106,21 @@ devlinks_xa_find_get(struct net *net, unsigned long *indexp,
* This prevents live-lock of devlink_unregister() wait for completion. * This prevents live-lock of devlink_unregister() wait for completion.
*/ */
if (xa_get_mark(&devlinks, *indexp, DEVLINK_UNREGISTERING)) 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)) if (!devlink_try_get(devlink))
goto retry; goto next;
if (!net_eq(devlink_net(devlink), net)) { if (!net_eq(devlink_net(devlink), net)) {
devlink_put(devlink); devlink_put(devlink);
goto retry; goto next;
} }
unlock: unlock:
rcu_read_unlock(); rcu_read_unlock();
return devlink; 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 * next:
devlinks_xa_find_get_next(struct net *net, unsigned long *indexp) (*indexp)++;
{ goto retry;
return devlinks_xa_find_get(net, indexp, xa_find_after);
} }
/** /**
......
...@@ -82,18 +82,9 @@ extern struct genl_family devlink_nl_family; ...@@ -82,18 +82,9 @@ extern struct genl_family devlink_nl_family;
* in loop body in order to release the reference. * in loop body in order to release the reference.
*/ */
#define devlinks_xa_for_each_registered_get(net, index, devlink) \ #define devlinks_xa_for_each_registered_get(net, index, devlink) \
for (index = 0, \ for (index = 0; (devlink = devlinks_xa_find_get(net, &index)); index++)
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);
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);
/* Netlink */ /* Netlink */
#define DEVLINK_NL_FLAG_NEED_PORT BIT(0) #define DEVLINK_NL_FLAG_NEED_PORT BIT(0)
...@@ -135,7 +126,7 @@ struct devlink_gen_cmd { ...@@ -135,7 +126,7 @@ struct devlink_gen_cmd {
*/ */
#define devlink_dump_for_each_instance_get(msg, state, devlink) \ #define devlink_dump_for_each_instance_get(msg, state, devlink) \
for (; (devlink = devlinks_xa_find_get(sock_net(msg->sk), \ for (; (devlink = devlinks_xa_find_get(sock_net(msg->sk), \
&state->instance, xa_find)); \ &state->instance)); \
state->instance++, state->idx = 0) state->instance++, state->idx = 0)
extern const struct genl_small_ops devlink_nl_ops[56]; extern const struct genl_small_ops devlink_nl_ops[56];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment