diff options
author | Jakub Kicinski <kuba@kernel.org> | 2023-01-05 07:05:30 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-01-06 09:13:39 +0300 |
commit | 07f3af66089e20fe439b219d3c9d3e68d964193f (patch) | |
tree | 4da8ef518b5f8f54ae106536e7c58996f0ba7502 /net/devlink/netlink.c | |
parent | e4d5015bc11bcc5123ec8805d8c7f1e28a77a8a9 (diff) | |
download | linux-07f3af66089e20fe439b219d3c9d3e68d964193f.tar.xz |
devlink: add by-instance dump infra
Most dumpit implementations walk the devlink instances.
This requires careful lock taking and reference dropping.
Factor the loop out and provide just a callback to handle
a single instance dump.
Convert one user as an example, other users converted
in the next change.
Slightly inspired by ethtool netlink code.
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/devlink/netlink.c')
-rw-r--r-- | net/devlink/netlink.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c index ce1a7d674d14..82ee5621bd9c 100644 --- a/net/devlink/netlink.c +++ b/net/devlink/netlink.c @@ -5,6 +5,7 @@ */ #include <net/genetlink.h> +#include <net/sock.h> #include "devl_internal.h" @@ -177,6 +178,39 @@ static void devlink_nl_post_doit(const struct genl_split_ops *ops, devlink_put(devlink); } +static const struct devlink_gen_cmd *devl_gen_cmds[] = { + [DEVLINK_CMD_RATE_GET] = &devl_gen_rate_get, +}; + +int devlink_nl_instance_iter_dump(struct sk_buff *msg, + struct netlink_callback *cb) +{ + const struct genl_dumpit_info *info = genl_dumpit_info(cb); + struct devlink_nl_dump_state *state = devlink_dump_state(cb); + const struct devlink_gen_cmd *cmd; + struct devlink *devlink; + int err = 0; + + cmd = devl_gen_cmds[info->op.cmd]; + + devlink_dump_for_each_instance_get(msg, state, devlink) { + devl_lock(devlink); + err = cmd->dump_one(msg, devlink, cb); + devl_unlock(devlink); + devlink_put(devlink); + + if (err) + break; + + /* restart sub-object walk for the next instance */ + state->idx = 0; + } + + if (err != -EMSGSIZE) + return err; + return msg->len; +} + struct genl_family devlink_nl_family __ro_after_init = { .name = DEVLINK_GENL_NAME, .version = DEVLINK_GENL_VERSION, |