diff options
| author | Christoph Böhmwalder <christoph.boehmwalder@linbit.com> | 2026-05-06 14:45:41 +0200 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-05-08 19:23:23 -0600 |
| commit | 8098eeb693c4cc4e774c62fbd4875197cb5578ce (patch) | |
| tree | 9357b663ae4972d3a95d2b1dd4fb6ffb7b2f460e | |
| parent | a54f499838292c1768f6575ed1ec7cf35f1b6489 (diff) | |
drbd: replace genl_magic with explicit netlink serialization
Replace the genl_magic multi-include macro system with explicit
serialization and parsing.
The *_gen files were initially produced from a YNL spec via a
customized ynl-gen-c, but the DRBD netlink family is effectively
frozen, so the generator is kept unmodified.
All new functionality will land in a separate, properly-designed
family.
Carry the resulting code as ordinary in-tree source rather than
landing the spec and generator changes that produced it.
The bulk of the changes are mechanical renames to fit the YNL naming
conventions:
- Handler functions: drbd_adm_* -> drbd_nl_*_doit/dumpit
- GENL_MAGIC_VERSION -> DRBD_FAMILY_VERSION
- GENL_MAGIC_FAMILY_HDRSZ -> sizeof(struct drbd_genlmsghdr)
- drbd_genl_family -> drbd_nl_family
- Attribute IDs: T_* -> DRBD_A_*
Remove the nested_attr_tb static global buffer and move to a per-call
allocation approach: each deserialization manages its own nested
attribute table. This will be needed anyway when we eventually move
to parallel_ops, and it's actually simpler this way, so make the
move now.
Replace the functionality of the "sensitive" flag: this was only used
by a single field (shared_secret); open-code redaction logic for that
locally.
Also replace the "invariant" flag: this only had a couple of users,
and those basically never change. Hard code the check directly inline.
The genl_family struct itself is defined manually in drbd_nl.c.
Also replace a couple of drbd-specific wrappers (nla_put_u64_0pad,
drbd_nla_find_nested) with standard kernel functions while we're at
it.
Finally, completely remove the genl_magic system; DRBD was its only
user.
Signed-off-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20260506124541.1951772-3-christoph.boehmwalder@linbit.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
| -rw-r--r-- | drivers/block/drbd/Makefile | 1 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_debugfs.c | 2 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_int.h | 4 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_main.c | 6 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_nl.c | 416 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_nl_gen.c | 2606 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_nl_gen.h | 395 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_proc.c | 2 | ||||
| -rw-r--r-- | include/linux/drbd_genl.h | 536 | ||||
| -rw-r--r-- | include/linux/drbd_genl_api.h | 16 | ||||
| -rw-r--r-- | include/linux/genl_magic_func.h | 413 | ||||
| -rw-r--r-- | include/linux/genl_magic_struct.h | 272 | ||||
| -rw-r--r-- | include/uapi/linux/drbd.h | 3 | ||||
| -rw-r--r-- | include/uapi/linux/drbd_genl.h | 359 |
14 files changed, 3609 insertions, 1422 deletions
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile index 187eaf81f0f8..5faaa8a8e7f0 100644 --- a/drivers/block/drbd/Makefile +++ b/drivers/block/drbd/Makefile @@ -3,6 +3,7 @@ drbd-y := drbd_buildtag.o drbd_bitmap.o drbd_proc.o drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o drbd-y += drbd_main.o drbd_strings.o drbd_nl.o drbd-y += drbd_interval.o drbd_state.o +drbd-y += drbd_nl_gen.o drbd-$(CONFIG_DEBUG_FS) += drbd_debugfs.o obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o diff --git a/drivers/block/drbd/drbd_debugfs.c b/drivers/block/drbd/drbd_debugfs.c index 12460b584bcb..371abcd7e880 100644 --- a/drivers/block/drbd/drbd_debugfs.c +++ b/drivers/block/drbd/drbd_debugfs.c @@ -844,7 +844,7 @@ static int drbd_version_show(struct seq_file *m, void *ignored) { seq_printf(m, "# %s\n", drbd_buildtag()); seq_printf(m, "VERSION=%s\n", REL_VERSION); - seq_printf(m, "API_VERSION=%u\n", GENL_MAGIC_VERSION); + seq_printf(m, "API_VERSION=%u\n", DRBD_FAMILY_VERSION); seq_printf(m, "PRO_VERSION_MIN=%u\n", PRO_VERSION_MIN); seq_printf(m, "PRO_VERSION_MAX=%u\n", PRO_VERSION_MAX); return 0; diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index f3d746a6d6fd..48b45c3142f7 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -32,14 +32,16 @@ #include <net/tcp.h> #include <linux/lru_cache.h> #include <linux/prefetch.h> -#include <linux/drbd_genl_api.h> #include <linux/drbd.h> #include "drbd_config.h" +#include "drbd_nl_gen.h" #include "drbd_strings.h" #include "drbd_state.h" #include "drbd_protocol.h" #include "drbd_polymorph_printk.h" +extern struct genl_family drbd_nl_family; + /* shared module parameters, defined in drbd_main.c */ #ifdef CONFIG_DRBD_FAULT_INJECTION extern int drbd_enable_faults; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index b1a721dd0496..a2a841c89201 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2324,7 +2324,7 @@ static void drbd_cleanup(void) if (retry.wq) destroy_workqueue(retry.wq); - drbd_genl_unregister(); + genl_unregister_family(&drbd_nl_family); idr_for_each_entry(&drbd_devices, device, i) drbd_delete_device(device); @@ -2846,7 +2846,7 @@ static int __init drbd_init(void) mutex_init(&resources_mutex); INIT_LIST_HEAD(&drbd_resources); - err = drbd_genl_register(); + err = genl_register_family(&drbd_nl_family); if (err) { pr_err("unable to register generic netlink family\n"); goto fail; @@ -2876,7 +2876,7 @@ static int __init drbd_init(void) pr_info("initialized. " "Version: " REL_VERSION " (api:%d/proto:%d-%d)\n", - GENL_MAGIC_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX); + DRBD_FAMILY_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX); pr_info("%s\n", drbd_buildtag()); pr_info("registered as block device major %d\n", DRBD_MAJOR); return 0; /* Success! */ diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index c2ac555473e7..f9ffcd67607b 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -31,59 +31,13 @@ #include <net/genetlink.h> -/* .doit */ -// int drbd_adm_create_resource(struct sk_buff *skb, struct genl_info *info); -// int drbd_adm_delete_resource(struct sk_buff *skb, struct genl_info *info); - -int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_del_minor(struct sk_buff *skb, struct genl_info *info); - -int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_down(struct sk_buff *skb, struct genl_info *info); - -int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_suspend_io(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_get_status(struct sk_buff *skb, struct genl_info *info); -int drbd_adm_get_timeout_type(struct sk_buff *skb, struct genl_info *info); -/* .dumpit */ -int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb); -int drbd_adm_dump_resources(struct sk_buff *skb, struct netlink_callback *cb); -int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb); -int drbd_adm_dump_devices_done(struct netlink_callback *cb); -int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb); -int drbd_adm_dump_connections_done(struct netlink_callback *cb); -int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb); -int drbd_adm_dump_peer_devices_done(struct netlink_callback *cb); -int drbd_adm_get_initial_state(struct sk_buff *skb, struct netlink_callback *cb); - -#include <linux/drbd_genl_api.h> - -static int drbd_pre_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, struct genl_info *info); -static void drbd_post_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, struct genl_info *info); - -#define GENL_MAGIC_FAMILY_PRE_DOIT drbd_pre_doit -#define GENL_MAGIC_FAMILY_POST_DOIT drbd_post_doit - -#include <linux/genl_magic_func.h> +#include "drbd_nl_gen.h" + +static int drbd_genl_multicast_events(struct sk_buff *skb, gfp_t flags) +{ + return genlmsg_multicast(&drbd_nl_family, skb, 0, + DRBD_NLGRP_EVENTS, flags); +} static atomic_t drbd_genl_seq = ATOMIC_INIT(2); /* two. */ static atomic_t notify_genl_seq = ATOMIC_INIT(2); /* two. */ @@ -114,7 +68,7 @@ static int drbd_msg_put_info(struct sk_buff *skb, const char *info) if (!nla) return err; - err = nla_put_string(skb, T_info_text, info); + err = nla_put_string(skb, DRBD_A_DRBD_CFG_REPLY_INFO_TEXT, info); if (err) { nla_nest_cancel(skb, nla); return err; @@ -135,7 +89,7 @@ static int drbd_msg_sprintf_info(struct sk_buff *skb, const char *fmt, ...) if (!nla) return err; - txt = nla_reserve(skb, T_info_text, 256); + txt = nla_reserve(skb, DRBD_A_DRBD_CFG_REPLY_INFO_TEXT, 256); if (!txt) { nla_nest_cancel(skb, nla); return err; @@ -187,6 +141,15 @@ static const unsigned int drbd_genl_cmd_flags[] = { [DRBD_ADM_DOWN] = DRBD_ADM_NEED_RESOURCE, }; +/* Detect attempts to change invariant attributes in a _change_ handler. */ +#define has_invariant(ntb, attr) \ +({ \ + bool __found = !!(ntb)[attr]; \ + if (__found) \ + pr_info("must not change invariant attr: %s\n", #attr); \ + __found; \ +}) + /* * At this point, we still rely on the global genl_lock(). * If we want to avoid that, and allow "genl_family.parallel_ops", we may need @@ -210,7 +173,7 @@ static int drbd_adm_prepare(struct drbd_config_context *adm_ctx, } adm_ctx->reply_dh = genlmsg_put_reply(adm_ctx->reply_skb, - info, &drbd_genl_family, 0, cmd); + info, &drbd_nl_family, 0, cmd); /* put of a few bytes into a fresh skb of >= 4k will always succeed. * but anyways */ if (!adm_ctx->reply_dh) { @@ -223,9 +186,11 @@ static int drbd_adm_prepare(struct drbd_config_context *adm_ctx, adm_ctx->volume = VOLUME_UNSPECIFIED; if (info->attrs[DRBD_NLA_CFG_CONTEXT]) { + struct nlattr **ntb; struct nlattr *nla; - /* parse and validate only */ - err = drbd_cfg_context_from_attrs(NULL, info); + + /* parse and validate, get nested attribute table */ + err = drbd_cfg_context_ntb_from_attrs(&ntb, info); if (err) goto fail; @@ -234,18 +199,21 @@ static int drbd_adm_prepare(struct drbd_config_context *adm_ctx, err = nla_put_nohdr(adm_ctx->reply_skb, info->attrs[DRBD_NLA_CFG_CONTEXT]->nla_len, info->attrs[DRBD_NLA_CFG_CONTEXT]); - if (err) + if (err) { + kfree(ntb); goto fail; + } /* and assign stuff to the adm_ctx */ - nla = nested_attr_tb[T_ctx_volume]; + nla = ntb[DRBD_A_DRBD_CFG_CONTEXT_CTX_VOLUME]; if (nla) adm_ctx->volume = nla_get_u32(nla); - nla = nested_attr_tb[T_ctx_resource_name]; + nla = ntb[DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME]; if (nla) adm_ctx->resource_name = nla_data(nla); - adm_ctx->my_addr = nested_attr_tb[T_ctx_my_addr]; - adm_ctx->peer_addr = nested_attr_tb[T_ctx_peer_addr]; + adm_ctx->my_addr = ntb[DRBD_A_DRBD_CFG_CONTEXT_CTX_MY_ADDR]; + adm_ctx->peer_addr = ntb[DRBD_A_DRBD_CFG_CONTEXT_CTX_PEER_ADDR]; + kfree(ntb); if ((adm_ctx->my_addr && nla_len(adm_ctx->my_addr) > sizeof(adm_ctx->connection->my_addr)) || (adm_ctx->peer_addr && @@ -259,7 +227,7 @@ static int drbd_adm_prepare(struct drbd_config_context *adm_ctx, adm_ctx->device = minor_to_device(d_in->minor); /* We are protected by the global genl_lock(). - * But we may explicitly drop it/retake it in drbd_adm_set_role(), + * But we may explicitly drop it/retake it in drbd_nl_set_role(), * so make sure this object stays around. */ if (adm_ctx->device) kref_get(&adm_ctx->device->kref); @@ -334,8 +302,8 @@ fail: return err; } -static int drbd_pre_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, struct genl_info *info) +int drbd_pre_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx; u8 cmd = info->genlhdr->cmd; @@ -362,8 +330,8 @@ static int drbd_pre_doit(const struct genl_split_ops *ops, return 0; } -static void drbd_post_doit(const struct genl_split_ops *ops, - struct sk_buff *skb, struct genl_info *info) +void drbd_post_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; @@ -828,7 +796,7 @@ static const char *from_attrs_err_to_txt(int err) "invalid attribute value"; } -int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info) +static int drbd_nl_set_role(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct set_role_parms parms; @@ -868,6 +836,16 @@ out: return 0; } +int drbd_nl_primary_doit(struct sk_buff *skb, struct genl_info *info) +{ + return drbd_nl_set_role(skb, info); +} + +int drbd_nl_secondary_doit(struct sk_buff *skb, struct genl_info *info) +{ + return drbd_nl_set_role(skb, info); +} + /* Initializes the md.*_offset members, so we are able to find * the on disk meta data. * @@ -962,7 +940,7 @@ char *ppsize(char *buf, unsigned long long size) * peer may not initiate a resize. */ /* Note these are not to be confused with - * drbd_adm_suspend_io/drbd_adm_resume_io, + * drbd_nl_suspend_io_doit/drbd_nl_resume_io_doit, * which are (sub) state changes triggered by admin (drbdsetup), * and can be long lived. * This changes an device->flag, is triggered by drbd internals, @@ -1574,13 +1552,14 @@ out: return err; } -int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_chg_disk_opts_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; enum drbd_ret_code retcode; struct drbd_device *device; struct disk_conf *new_disk_conf, *old_disk_conf; struct fifo_buffer *old_plan = NULL, *new_plan = NULL; + struct nlattr **ntb; int err; unsigned int fifo_size; @@ -1612,13 +1591,29 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) if (should_set_defaults(info)) set_disk_conf_defaults(new_disk_conf); - err = disk_conf_from_attrs_for_change(new_disk_conf, info); + err = disk_conf_from_attrs(new_disk_conf, info); if (err && err != -ENOMSG) { retcode = ERR_MANDATORY_TAG; drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail_unlock; } + err = disk_conf_ntb_from_attrs(&ntb, info); + if (!err) { + if (has_invariant(ntb, DRBD_A_DISK_CONF_BACKING_DEV) || + has_invariant(ntb, DRBD_A_DISK_CONF_META_DEV) || + has_invariant(ntb, DRBD_A_DISK_CONF_META_DEV_IDX) || + has_invariant(ntb, DRBD_A_DISK_CONF_DISK_SIZE) || + has_invariant(ntb, DRBD_A_DISK_CONF_MAX_BIO_BVECS)) { + retcode = ERR_MANDATORY_TAG; + drbd_msg_put_info(adm_ctx->reply_skb, + "cannot change invariant setting"); + kfree(ntb); + goto fail_unlock; + } + kfree(ntb); + } + if (!expect(device, new_disk_conf->resync_rate >= 1)) new_disk_conf->resync_rate = 1; @@ -1796,7 +1791,7 @@ void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev * kfree(ldev); } -int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_attach_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct drbd_device *device; @@ -2236,7 +2231,7 @@ static int adm_detach(struct drbd_device *device, int force) * Then we transition to D_DISKLESS, and wait for put_ldev() to return all * internal references as well. * Only then we have finally detached. */ -int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_detach_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; enum drbd_ret_code retcode; @@ -2434,12 +2429,13 @@ static void free_crypto(struct crypto *crypto) crypto_free_shash(crypto->verify_tfm); } -int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_chg_net_opts_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; enum drbd_ret_code retcode; struct drbd_connection *connection; struct net_conf *old_net_conf, *new_net_conf = NULL; + struct nlattr **ntb; int err; int ovr; /* online verify running */ int rsr; /* re-sync running */ @@ -2476,13 +2472,26 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) if (should_set_defaults(info)) set_net_conf_defaults(new_net_conf); - err = net_conf_from_attrs_for_change(new_net_conf, info); + err = net_conf_from_attrs(new_net_conf, info); if (err && err != -ENOMSG) { retcode = ERR_MANDATORY_TAG; drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } + err = net_conf_ntb_from_attrs(&ntb, info); + if (!err) { + if (has_invariant(ntb, DRBD_A_NET_CONF_DISCARD_MY_DATA) || + has_invariant(ntb, DRBD_A_NET_CONF_TENTATIVE)) { + retcode = ERR_MANDATORY_TAG; + drbd_msg_put_info(adm_ctx->reply_skb, + "cannot change invariant setting"); + kfree(ntb); + goto fail; + } + kfree(ntb); + } + retcode = check_net_options(connection, new_net_conf); if (retcode != NO_ERROR) goto fail; @@ -2575,7 +2584,7 @@ static void peer_device_to_info(struct peer_device_info *info, info->peer_resync_susp_dependency = device->state.aftr_isp; } -int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_connect_doit(struct sk_buff *skb, struct genl_info *info) { struct connection_info connection_info; enum drbd_notification_type flags; @@ -2790,7 +2799,7 @@ repeat: return rv; } -int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_disconnect_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct disconnect_parms parms; @@ -2845,7 +2854,7 @@ void resync_after_online_grow(struct drbd_device *device) _drbd_request_state(device, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE + CS_SERIALIZE); } -int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_resize_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct disk_conf *old_disk_conf, *new_disk_conf = NULL; @@ -2981,7 +2990,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) goto fail; } -int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_resource_opts_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; enum drbd_ret_code retcode; @@ -3019,7 +3028,7 @@ fail: return 0; } -int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_invalidate_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct drbd_device *device; @@ -3097,7 +3106,7 @@ static int drbd_bmio_set_susp_al(struct drbd_device *device, return rv; } -int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_inval_peer_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; int retcode; /* drbd_ret_code, drbd_state_rv */ @@ -3148,7 +3157,7 @@ out: return 0; } -int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_pause_sync_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; enum drbd_ret_code retcode; @@ -3168,7 +3177,7 @@ out: return 0; } -int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_resume_sync_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; union drbd_dev_state s; @@ -3196,12 +3205,12 @@ out: return 0; } -int drbd_adm_suspend_io(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_suspend_io_doit(struct sk_buff *skb, struct genl_info *info) { return drbd_adm_simple_request_state(skb, info, NS(susp, 1)); } -int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_resume_io_doit(struct sk_buff *skb, struct genl_info *info) { struct drbd_config_context *adm_ctx = info->user_ptr[0]; struct drbd_device *device; @@ -3257,7 +3266,7 @@ out: return 0; } -int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info) +int drbd_nl_outdate_doit(struct sk_buff *skb, struct genl_info *info) { return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED)); } @@ -3272,16 +3281,20 @@ static int nla_put_drbd_cfg_context(struct sk_buff *skb, if (!nla) goto nla_put_failure; if (device && - nla_put_u32(skb, T_ctx_volume, device->vnr)) + nla_put_u32(skb, DRBD_A_DRBD_CFG_CONTEXT_CTX_VOLUME, device->vnr)) goto nla_put_failure; - if (nla_put_string(skb, T_ctx_resource_name, resource->name)) + if (nla_put_string(skb, DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME, resource->name)) goto nla_put_failure; if (connection) { if (connection->my_addr_len && - nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr)) + nla_put(skb, DRBD_A_DRBD_CFG_CONTEXT_CTX_MY_ADDR, + connection->my_addr_len, + &connection->my_addr)) goto nla_put_failure; if (connection->peer_addr_len && - nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr)) + nla_put(skb, DRBD_A_DRBD_CFG_CONTEXT_CTX_PEER_ADDR, + connection->peer_addr_len, + &connection->peer_addr)) goto nla_put_failure; } nla_nest_end(skb, nla); @@ -3300,7 +3313,7 @@ nla_put_failure: */ static struct nlattr *find_cfg_context_attr(const struct nlmsghdr *nlh, int attr) { - const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ; + const unsigned int hdrlen = GENL_HDRLEN + sizeof(struct drbd_genlmsghdr); struct nlattr *nla; nla = nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), @@ -3312,7 +3325,7 @@ static struct nlattr *find_cfg_context_attr(const struct nlmsghdr *nlh, int attr static void resource_to_info(struct resource_info *, struct drbd_resource *); -int drbd_adm_dump_resources(struct sk_buff *skb, struct netlink_callback *cb) +int drbd_nl_get_resources_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { struct drbd_genlmsghdr *dh; struct drbd_resource *resource; @@ -3340,7 +3353,7 @@ found_resource: put_result: dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, &drbd_genl_family, + cb->nlh->nlmsg_seq, &drbd_nl_family, NLM_F_MULTI, DRBD_ADM_GET_RESOURCES); err = -ENOMEM; if (!dh) @@ -3350,15 +3363,15 @@ put_result: err = nla_put_drbd_cfg_context(skb, resource, NULL, NULL); if (err) goto out; - err = res_opts_to_skb(skb, &resource->res_opts, !capable(CAP_SYS_ADMIN)); + err = res_opts_to_skb(skb, &resource->res_opts); if (err) goto out; resource_to_info(&resource_info, resource); - err = resource_info_to_skb(skb, &resource_info, !capable(CAP_SYS_ADMIN)); + err = resource_info_to_skb(skb, &resource_info); if (err) goto out; resource_statistics.res_stat_write_ordering = resource->write_ordering; - err = resource_statistics_to_skb(skb, &resource_statistics, !capable(CAP_SYS_ADMIN)); + err = resource_statistics_to_skb(skb, &resource_statistics); if (err) goto out; cb->args[0] = (long)resource; @@ -3423,7 +3436,7 @@ int drbd_adm_dump_devices_done(struct netlink_callback *cb) { static void device_to_info(struct device_info *, struct drbd_device *); -int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb) +int drbd_nl_get_devices_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource; @@ -3436,7 +3449,8 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb) resource = (struct drbd_resource *)cb->args[0]; if (!cb->args[0] && !cb->args[1]) { - resource_filter = find_cfg_context_attr(cb->nlh, T_ctx_resource_name); + resource_filter = find_cfg_context_attr(cb->nlh, + DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME); if (resource_filter) { retcode = ERR_RES_NOT_KNOWN; resource = drbd_find_resource(nla_data(resource_filter)); @@ -3465,7 +3479,7 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb) put_result: dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, &drbd_genl_family, + cb->nlh->nlmsg_seq, &drbd_nl_family, NLM_F_MULTI, DRBD_ADM_GET_DEVICES); err = -ENOMEM; if (!dh) @@ -3481,18 +3495,18 @@ put_result: struct disk_conf *disk_conf = rcu_dereference(device->ldev->disk_conf); - err = disk_conf_to_skb(skb, disk_conf, !capable(CAP_SYS_ADMIN)); + err = disk_conf_to_skb(skb, disk_conf); put_ldev(device); if (err) goto out; } device_to_info(&device_info, device); - err = device_info_to_skb(skb, &device_info, !capable(CAP_SYS_ADMIN)); + err = device_info_to_skb(skb, &device_info); if (err) goto out; device_to_statistics(&device_statistics, device); - err = device_statistics_to_skb(skb, &device_statistics, !capable(CAP_SYS_ADMIN)); + err = device_statistics_to_skb(skb, &device_statistics); if (err) goto out; cb->args[1] = minor + 1; @@ -3514,7 +3528,7 @@ int drbd_adm_dump_connections_done(struct netlink_callback *cb) enum { SINGLE_RESOURCE, ITERATE_RESOURCES }; -int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb) +int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource = NULL, *next_resource; @@ -3527,7 +3541,8 @@ int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); resource = (struct drbd_resource *)cb->args[0]; if (!cb->args[0]) { - resource_filter = find_cfg_context_attr(cb->nlh, T_ctx_resource_name); + resource_filter = find_cfg_context_attr(cb->nlh, + DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME); if (resource_filter) { retcode = ERR_RES_NOT_KNOWN; resource = drbd_find_resource(nla_data(resource_filter)); @@ -3591,7 +3606,7 @@ found_resource: put_result: dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, &drbd_genl_family, + cb->nlh->nlmsg_seq, &drbd_nl_family, NLM_F_MULTI, DRBD_ADM_GET_CONNECTIONS); err = -ENOMEM; if (!dh) @@ -3606,16 +3621,16 @@ put_result: goto out; net_conf = rcu_dereference(connection->net_conf); if (net_conf) { - err = net_conf_to_skb(skb, net_conf, !capable(CAP_SYS_ADMIN)); + err = net_conf_to_skb(skb, net_conf); if (err) goto out; } connection_to_info(&connection_info, connection); - err = connection_info_to_skb(skb, &connection_info, !capable(CAP_SYS_ADMIN)); + err = connection_info_to_skb(skb, &connection_info); if (err) goto out; connection_statistics.conn_congested = test_bit(NET_CONGESTED, &connection->flags); - err = connection_statistics_to_skb(skb, &connection_statistics, !capable(CAP_SYS_ADMIN)); + err = connection_statistics_to_skb(skb, &connection_statistics); if (err) goto out; cb->args[2] = (long)connection; @@ -3676,7 +3691,7 @@ int drbd_adm_dump_peer_devices_done(struct netlink_callback *cb) return put_resource_in_arg0(cb, 9); } -int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb) +int drbd_nl_get_peer_devices_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource; @@ -3688,7 +3703,8 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb) resource = (struct drbd_resource *)cb->args[0]; if (!cb->args[0] && !cb->args[1]) { - resource_filter = find_cfg_context_attr(cb->nlh, T_ctx_resource_name); + resource_filter = find_cfg_context_attr(cb->nlh, + DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME); if (resource_filter) { retcode = ERR_RES_NOT_KNOWN; resource = drbd_find_resource(nla_data(resource_filter)); @@ -3735,7 +3751,7 @@ found_peer_device: put_result: dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, &drbd_genl_family, + cb->nlh->nlmsg_seq, &drbd_nl_family, NLM_F_MULTI, DRBD_ADM_GET_PEER_DEVICES); err = -ENOMEM; if (!dh) @@ -3751,11 +3767,11 @@ put_result: if (err) goto out; peer_device_to_info(&peer_device_info, peer_device); - err = peer_device_info_to_skb(skb, &peer_device_info, !capable(CAP_SYS_ADMIN)); + err = peer_device_info_to_skb(skb, &peer_device_info); if (err) goto out; peer_device_to_statistics(&peer_device_statistics, peer_device); - err = peer_device_statistics_to_skb(skb, &peer_device_statistics, !capable(CAP_SYS_ADMIN)); + err = peer_device_statistics_to_skb(skb, &peer_device_statistics); if (err) goto out; cb->args[1] = minor; @@ -3795,11 +3811,11 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, /* If sib != NULL, this is drbd_bcast_event, which anyone can listen * to. So we better exclude_sensitive information. * - * If sib == NULL, this is drbd_adm_get_status, executed synchronously + * If sib == NULL, this is drbd_nl_get_status_doit, executed synchronously * in the context of the requesting user process. Exclude sensitive * information, unless current has superuser. * - * NOTE: for drbd_adm_get_status_all(), this is a netlink dump, and + * NOTE: for drbd_nl_get_status_dumpit(), this is a netlink dump, and * relies on the current implementation of netlink_dump(), which * executes the dump callback successively from netlink_recvmsg(), * always in the context of the receiving process */ @@ -3812,7 +3828,7 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, if (nla_put_drbd_cfg_context(skb, resource, the_only_connection(resource), device)) goto nla_put_failure; - if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive)) + if (res_opts_to_skb(skb, &device->resource->res_opts)) goto nla_put_failure; rcu_read_lock(); @@ -3820,14 +3836,24 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, struct disk_conf *disk_conf; disk_conf = rcu_dereference(device->ldev->disk_conf); - err = disk_conf_to_skb(skb, disk_conf, exclude_sensitive); + err = disk_conf_to_skb(skb, disk_conf); } if (!err) { struct net_conf *nc; nc = rcu_dereference(first_peer_device(device)->connection->net_conf); - if (nc) - err = net_conf_to_skb(skb, nc, exclude_sensitive); + if (nc) { + if (exclude_sensitive) { + struct net_conf nc_clean = *nc; + + memset(nc_clean.shared_secret, 0, + sizeof(nc_clean.shared_secret)); + nc_clean.shared_secret_len = 0; + err = net_conf_to_skb(skb, &nc_clean); + } else { + err = net_conf_to_skb(skb, nc); + } + } } rcu_read_unlock(); if (err) @@ -3836,42 +3862,57 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, nla = nla_nest_start_noflag(skb, DRBD_NLA_STATE_INFO); if (!nla) goto nla_put_failure; - if (nla_put_u32(skb, T_sib_reason, sib ? sib->sib_reason : SIB_GET_STATUS_REPLY) || - nla_put_u32(skb, T_current_state, device->state.i) || - nla_put_u64_0pad(skb, T_ed_uuid, device->ed_uuid) || - nla_put_u64_0pad(skb, T_capacity, get_capacity(device->vdisk)) || - nla_put_u64_0pad(skb, T_send_cnt, device->send_cnt) || - nla_put_u64_0pad(skb, T_recv_cnt, device->recv_cnt) || - nla_put_u64_0pad(skb, T_read_cnt, device->read_cnt) || - nla_put_u64_0pad(skb, T_writ_cnt, device->writ_cnt) || - nla_put_u64_0pad(skb, T_al_writ_cnt, device->al_writ_cnt) || - nla_put_u64_0pad(skb, T_bm_writ_cnt, device->bm_writ_cnt) || - nla_put_u32(skb, T_ap_bio_cnt, atomic_read(&device->ap_bio_cnt)) || - nla_put_u32(skb, T_ap_pending_cnt, atomic_read(&device->ap_pending_cnt)) || - nla_put_u32(skb, T_rs_pending_cnt, atomic_read(&device->rs_pending_cnt))) + if (nla_put_u32(skb, DRBD_A_STATE_INFO_SIB_REASON, + sib ? sib->sib_reason : SIB_GET_STATUS_REPLY) || + nla_put_u32(skb, DRBD_A_STATE_INFO_CURRENT_STATE, + device->state.i) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_ED_UUID, + device->ed_uuid, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_CAPACITY, + get_capacity(device->vdisk), 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_SEND_CNT, + device->send_cnt, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_RECV_CNT, + device->recv_cnt, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_READ_CNT, + device->read_cnt, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_WRIT_CNT, + device->writ_cnt, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_AL_WRIT_CNT, + device->al_writ_cnt, 0) || + nla_put_u64_64bit(skb, DRBD_A_STATE_INFO_BM_WRIT_CNT, + device->bm_writ_cnt, 0) || + nla_put_u32(skb, DRBD_A_STATE_INFO_AP_BIO_CNT, + atomic_read(&device->ap_bio_cnt)) || + nla_put_u32(skb, DRBD_A_STATE_INFO_AP_PENDING_CNT, + atomic_read(&device->ap_pending_cnt)) || + nla_put_u32(skb, DRBD_A_STATE_INF |
