Skip to content

Commit

Permalink
Merge branch 'clean-devlink-net-namespace-operations'
Browse files Browse the repository at this point in the history
Leon Romanovsky says:

====================
Clean devlink net namespace operations

This short series continues my work on devlink core code to make devlink
reload less prone to errors and harden it from API abuse.

Despite first patch being a clear fix, I would ask you to apply it to
net-next anyway, because the fixed patch is anyway old and it will
help us to eliminate merge conflicts that will arise for following
patches or even for the second one.
====================

Link: https://lore.kernel.org/r/cover.1627578998.git.leonro@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Jul 30, 2021
2 parents a432934 + 2671345 commit aae950b
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 33 deletions.
4 changes: 2 additions & 2 deletions drivers/net/netdevsim/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1431,10 +1431,10 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
struct devlink *devlink;
int err;

devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev));
devlink = devlink_alloc_ns(&nsim_dev_devlink_ops, sizeof(*nsim_dev),
nsim_bus_dev->initial_net);
if (!devlink)
return -ENOMEM;
devlink_net_set(devlink, nsim_bus_dev->initial_net);
nsim_dev = devlink_priv(devlink);
nsim_dev->nsim_bus_dev = nsim_bus_dev;
nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
Expand Down
14 changes: 12 additions & 2 deletions include/net/devlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -1540,8 +1540,18 @@ static inline struct devlink *netdev_to_devlink(struct net_device *dev)
struct ib_device;

struct net *devlink_net(const struct devlink *devlink);
void devlink_net_set(struct devlink *devlink, struct net *net);
struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size);
/* This call is intended for software devices that can create
* devlink instances in other namespaces than init_net.
*
* Drivers that operate on real HW must use devlink_alloc() instead.
*/
struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
size_t priv_size, struct net *net);
static inline struct devlink *devlink_alloc(const struct devlink_ops *ops,
size_t priv_size)
{
return devlink_alloc_ns(ops, priv_size, &init_net);
}
int devlink_register(struct devlink *devlink, struct device *dev);
void devlink_unregister(struct devlink *devlink);
void devlink_reload_enable(struct devlink *devlink);
Expand Down
56 changes: 27 additions & 29 deletions net/core/devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,6 @@ struct net *devlink_net(const struct devlink *devlink)
}
EXPORT_SYMBOL_GPL(devlink_net);

static void __devlink_net_set(struct devlink *devlink, struct net *net)
{
write_pnet(&devlink->_net, net);
}

void devlink_net_set(struct devlink *devlink, struct net *net)
{
if (WARN_ON(devlink->dev))
return;
__devlink_net_set(devlink, net);
}
EXPORT_SYMBOL_GPL(devlink_net_set);

static struct devlink *devlink_get_from_attrs(struct net *net,
struct nlattr **attrs)
{
Expand Down Expand Up @@ -3801,28 +3788,31 @@ static void devlink_param_notify(struct devlink *devlink,
struct devlink_param_item *param_item,
enum devlink_command cmd);

static void devlink_reload_netns_change(struct devlink *devlink,
struct net *dest_net)
static void devlink_ns_change_notify(struct devlink *devlink,
struct net *dest_net, struct net *curr_net,
bool new)
{
struct devlink_param_item *param_item;
enum devlink_command cmd;

/* Userspace needs to be notified about devlink objects
* removed from original and entering new network namespace.
* The rest of the devlink objects are re-created during
* reload process so the notifications are generated separatelly.
*/

list_for_each_entry(param_item, &devlink->param_list, list)
devlink_param_notify(devlink, 0, param_item,
DEVLINK_CMD_PARAM_DEL);
devlink_notify(devlink, DEVLINK_CMD_DEL);
if (!dest_net || net_eq(dest_net, curr_net))
return;

__devlink_net_set(devlink, dest_net);
if (new)
devlink_notify(devlink, DEVLINK_CMD_NEW);

devlink_notify(devlink, DEVLINK_CMD_NEW);
cmd = new ? DEVLINK_CMD_PARAM_NEW : DEVLINK_CMD_PARAM_DEL;
list_for_each_entry(param_item, &devlink->param_list, list)
devlink_param_notify(devlink, 0, param_item,
DEVLINK_CMD_PARAM_NEW);
devlink_param_notify(devlink, 0, param_item, cmd);

if (!new)
devlink_notify(devlink, DEVLINK_CMD_DEL);
}

static bool devlink_reload_supported(const struct devlink_ops *ops)
Expand Down Expand Up @@ -3902,25 +3892,30 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
u32 *actions_performed, struct netlink_ext_ack *extack)
{
u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
struct net *curr_net;
int err;

if (!devlink->reload_enabled)
return -EOPNOTSUPP;

memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
sizeof(remote_reload_stats));

curr_net = devlink_net(devlink);
devlink_ns_change_notify(devlink, dest_net, curr_net, false);
err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
if (err)
return err;

if (dest_net && !net_eq(dest_net, devlink_net(devlink)))
devlink_reload_netns_change(devlink, dest_net);
if (dest_net && !net_eq(dest_net, curr_net))
write_pnet(&devlink->_net, dest_net);

err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
devlink_reload_failed_set(devlink, !!err);
if (err)
return err;

devlink_ns_change_notify(devlink, dest_net, curr_net, true);
WARN_ON(!(*actions_performed & BIT(action)));
/* Catch driver on updating the remote action within devlink reload */
WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
Expand Down Expand Up @@ -8768,15 +8763,18 @@ static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
}

/**
* devlink_alloc - Allocate new devlink instance resources
* devlink_alloc_ns - Allocate new devlink instance resources
* in specific namespace
*
* @ops: ops
* @priv_size: size of user private data
* @net: net namespace
*
* Allocate new devlink instance resources, including devlink index
* and name.
*/
struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
struct devlink *devlink_alloc_ns(const struct devlink_ops *ops,
size_t priv_size, struct net *net)
{
struct devlink *devlink;

Expand All @@ -8791,7 +8789,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
return NULL;
devlink->ops = ops;
xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
__devlink_net_set(devlink, &init_net);
write_pnet(&devlink->_net, net);
INIT_LIST_HEAD(&devlink->port_list);
INIT_LIST_HEAD(&devlink->rate_list);
INIT_LIST_HEAD(&devlink->sb_list);
Expand All @@ -8807,7 +8805,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
mutex_init(&devlink->reporters_lock);
return devlink;
}
EXPORT_SYMBOL_GPL(devlink_alloc);
EXPORT_SYMBOL_GPL(devlink_alloc_ns);

/**
* devlink_register - Register devlink instance
Expand Down

0 comments on commit aae950b

Please sign in to comment.