summaryrefslogtreecommitdiff
path: root/net/devlink/netlink.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2023-01-04 20:05:30 -0800
committerJakub Kicinski <kuba@kernel.org>2023-01-05 22:13:39 -0800
commit07f3af66089e20fe439b219d3c9d3e68d964193f (patch)
tree4da8ef518b5f8f54ae106536e7c58996f0ba7502 /net/devlink/netlink.c
parente4d5015bc11bcc5123ec8805d8c7f1e28a77a8a9 (diff)
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.c34
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,