From nobody Sun Apr 5 13:06:00 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C841406261 for ; Tue, 24 Mar 2026 15:29:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774366177; cv=none; b=Qzi4gBB6PS9YsM1+WhP9RDPy8gnjWcP/A7cETearotPiDl22dUYYFHBNuhH88r2pd7iOFJzVl24L6bUdeqGT3sgCqHOpkbaOkdNJMs1Y1zvuo2FSQcuBnmJUZaC/Ep8hDeo41cPbn0t88em29oD9BonPxBUKgBIe7odNW2itslc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774366177; c=relaxed/simple; bh=ew7Ttx26cAbUhQ5QxJtSWK6WWUa/qsIrByEV9tWKh78=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=gteYo5+AiOCkZRGcl+LwkDqumLQFw1InRGr+h/YvoYu9PaCRJIpRCgSB+QIbNHOYCHUARsgbPqvWdG280HmBfzwZhGrNMJM8QxiAJLHCWHEsurNlrWiChmAbV2GpePNVJhX9Jyy4BPfKyVD11zt3kbijH/VSbXA6FBFNEys8Abo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linbit.com; spf=pass smtp.mailfrom=linbit.com; dkim=pass (2048-bit key) header.d=linbit-com.20230601.gappssmtp.com header.i=@linbit-com.20230601.gappssmtp.com header.b=oeTedJJs; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linbit.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linbit.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linbit-com.20230601.gappssmtp.com header.i=@linbit-com.20230601.gappssmtp.com header.b="oeTedJJs" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-48702d51cd0so40487555e9.2 for ; Tue, 24 Mar 2026 08:29:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linbit-com.20230601.gappssmtp.com; s=20230601; t=1774366171; x=1774970971; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=AwVFOUDI8jos7wgB4yWql5shDVi/mFaLE8Zy0cbHbw4=; b=oeTedJJsXduZYaJgdeR6hK6zLyN1GOoL2M7zI/AAQoNQrOuVHu7ra5FOKIa3MumAqj Vqb9/ag2YWf2OovOfj58X5PqFctnnJrAFjBe6/nYvLDaL7xZJc3AuGP5kKlG/As6d691 p/tothfFDL6QlvOUJZhWD1WhcKy6amYfPQ3oIJ8HyLHVumTA9a8Z3rZTPBhrPPkR/0lM gOG+Q1ifyqoRAgqT9kStcW/MEQbxOXK9dGQ1I1Vday+3170cMoGQY4ZkwhvRFIvgxKNk BT0lZgugD1bzsDEZo4jd2JUMFIY4X38Q53X4iqywdKEbBSgWu6u/0XqWl8EBjWYdVZs4 PzPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774366171; x=1774970971; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=AwVFOUDI8jos7wgB4yWql5shDVi/mFaLE8Zy0cbHbw4=; b=Ww9++aFD0XjgCnwySTBrIFBi8w1yvEV78XOwEq+/41OwX3UbfC+RWzfsEHOE9oWxA7 m7M9BRlF2qAX+eYo/O2yjF7FfhjhayM0vJj5D2UJPKdetRqsXME0icdKgYWGilCSEjFa 2Yslv0F0cNsaELOssder8u1nz+JTRiCtHpN+6hm6mcVlf1hOVUNbovDCS5n5uipPu7kL ZTqZi7eU8uPJsWIjHrWwCxpUj2GJZwcGeH1ajXhSBk/0f9LSI/zACOaMQE6sT9su92Rg ZwXp0Lj2pS7MQmFZZIZ6ybkEacBvaS/sCLyolQ1ev6tef5dlO8e5hTPgaqMVWLoz4zh/ zOOQ== X-Forwarded-Encrypted: i=1; AJvYcCUXf51Po/UIpEyaLEUhofhYD/00SPJZ7RlrY3KPNx8cXD88sZ9TpUoe+BCm6NRySvDuDs40o2ZM7i8DeRE=@vger.kernel.org X-Gm-Message-State: AOJu0Ywgn/djf3qzsPhkjb3Z51myKVethGQCByC+WTVYhJbCX87bbpzf 42zWZPL4h3/XgpkZUAwjcIBOqYEvV1ct6iOh0U1wq+U24wL0k0NL8fv+J5JVdMPtfiE= X-Gm-Gg: ATEYQzy3TO53JZjxMVm+QIuOWuGfQ8703IFKfMogQIAdW+PBxYhhocIZlsIgyc+qdaK k931reJM+xoEg6z2fr5QthuGsdlsyc0x6MVOKlzVpt7yNAeePIxIP/9eTPIVMrHiN/5AI4ISeR6 lcOLLe7ebNYV/ony62F8U5rIAMr5E01HXRCAnGEHVzfSdxWRt3wq0t7LZYLUBBiftwXPpWrsJmW P31OUt0A1nLA42od6uVp8vgrHH6DhHBHAN0ZzC5uggC+fToyTxawXntfa2exWfVSgaP+ZuFwtMZ ys3BowPf989qluB19twyLTmWPaFC6lfzCps8C/jxP1m7MtdjLDzeWUJgPmcKZYvRx3xolCAUoKv Wqxnm7PHbwB4Q5Yo+dKHONQFIQFFF6Q4cUOvPJl3WUDcctqyE4NJ+w/P951VNqpRVd/Pb1bPBRZ Bwj8eW8RtE3kAkd2iZfFDWipbjB+uUFnPN3grq+gNokMTkiIHv1To/j6rqmFwRsu+YjxOEJLimG 3uulzpMCLZ7sPmy7ZpyNw== X-Received: by 2002:a05:600c:a088:b0:477:b734:8c53 with SMTP id 5b1f17b1804b1-48715fef727mr3062615e9.12.1774366171355; Tue, 24 Mar 2026 08:29:31 -0700 (PDT) Received: from localhost.localdomain (h082218028181.host.wavenet.at. [82.218.28.181]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48711764625sm60092705e9.14.2026.03.24.08.29.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Mar 2026 08:29:30 -0700 (PDT) From: =?UTF-8?q?Christoph=20B=C3=B6hmwalder?= To: Jens Axboe Cc: drbd-dev@lists.linbit.com, linux-kernel@vger.kernel.org, Lars Ellenberg , Philipp Reisner , linux-block@vger.kernel.org, =?UTF-8?q?Christoph=20B=C3=B6hmwalder?= Subject: [PATCH] drbd: use genl pre_doit/post_doit Date: Tue, 24 Mar 2026 16:29:07 +0100 Message-ID: <20260324152907.2840984-1-christoph.boehmwalder@linbit.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Every doit handler followed the same pattern: stack-allocate an adm_ctx, call drbd_adm_prepare() at the top, call drbd_adm_finish() at the bottom. This duplicated boilerplate across 25 handlers and made error paths inconsistent, since some handlers could miss sending the reply skb on early-exit paths. The generic netlink framework already provides pre_doit/post_doit hooks for exactly this purpose. An old comment even noted "this would be a good candidate for a pre_doit hook". Use them: - pre_doit heap-allocates adm_ctx, looks up per-command flags from a new drbd_genl_cmd_flags[] table, runs drbd_adm_prepare(), and stores the context in info->user_ptr[0]. - post_doit sends the reply, drops kref references for device/connection/resource, and frees the adm_ctx. - Handlers just receive adm_ctx from info->user_ptr[0], set reply_dh->ret_code, and return. All teardown is in post_doit. - drbd_adm_finish() is removed, superseded by post_doit. Signed-off-by: Christoph B=C3=B6hmwalder --- Some context: we are currently in the process of converting the old genl_magic macro infrastructure to YNL. This patch is a prerequisite to that work because it decouples the preperation/cleanup logic from the actual handlers. drivers/block/drbd/drbd_nl.c | 573 ++++++++++++++++++-------------- include/linux/genl_magic_func.h | 4 + 2 files changed, 324 insertions(+), 253 deletions(-) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index e201f0087a0f..e18fa260a662 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -75,6 +75,15 @@ int drbd_adm_get_initial_state(struct sk_buff *skb, stru= ct netlink_callback *cb) =20 #include #include "drbd_nla.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 =20 static atomic_t drbd_genl_seq =3D ATOMIC_INIT(2); /* two. */ @@ -144,18 +153,46 @@ static int drbd_msg_sprintf_info(struct sk_buff *skb,= const char *fmt, ...) return 0; } =20 -/* This would be a good candidate for a "pre_doit" hook, - * and per-family private info->pointers. - * But we need to stay compatible with older kernels. - * If it returns successfully, adm_ctx members are valid. - * +/* Flags for drbd_adm_prepare() */ +#define DRBD_ADM_NEED_MINOR (1 << 0) +#define DRBD_ADM_NEED_RESOURCE (1 << 1) +#define DRBD_ADM_NEED_CONNECTION (1 << 2) + +/* Per-command flags for drbd_pre_doit() */ +static const unsigned int drbd_genl_cmd_flags[] =3D { + [DRBD_ADM_GET_STATUS] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_NEW_MINOR] =3D DRBD_ADM_NEED_RESOURCE, + [DRBD_ADM_DEL_MINOR] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_NEW_RESOURCE] =3D 0, + [DRBD_ADM_DEL_RESOURCE] =3D DRBD_ADM_NEED_RESOURCE, + [DRBD_ADM_RESOURCE_OPTS] =3D DRBD_ADM_NEED_RESOURCE, + [DRBD_ADM_CONNECT] =3D DRBD_ADM_NEED_RESOURCE, + [DRBD_ADM_CHG_NET_OPTS] =3D DRBD_ADM_NEED_CONNECTION, + [DRBD_ADM_DISCONNECT] =3D DRBD_ADM_NEED_CONNECTION, + [DRBD_ADM_ATTACH] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_CHG_DISK_OPTS] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_RESIZE] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_PRIMARY] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_SECONDARY] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_NEW_C_UUID] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_START_OV] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_DETACH] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_INVALIDATE] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_INVAL_PEER] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_PAUSE_SYNC] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_RESUME_SYNC] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_SUSPEND_IO] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_RESUME_IO] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_OUTDATE] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_GET_TIMEOUT_TYPE] =3D DRBD_ADM_NEED_MINOR, + [DRBD_ADM_DOWN] =3D DRBD_ADM_NEED_RESOURCE, +}; + +/* * 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 * to add additional synchronization against object destruction/modificati= on. */ -#define DRBD_ADM_NEED_MINOR 1 -#define DRBD_ADM_NEED_RESOURCE 2 -#define DRBD_ADM_NEED_CONNECTION 4 static int drbd_adm_prepare(struct drbd_config_context *adm_ctx, struct sk_buff *skb, struct genl_info *info, unsigned flags) { @@ -163,8 +200,6 @@ static int drbd_adm_prepare(struct drbd_config_context = *adm_ctx, const u8 cmd =3D info->genlhdr->cmd; int err; =20 - memset(adm_ctx, 0, sizeof(*adm_ctx)); - /* genl_rcv_msg only checks for CAP_NET_ADMIN on "GENL_ADMIN_PERM" :( */ if (cmd !=3D DRBD_ADM_GET_STATUS && !capable(CAP_NET_ADMIN)) return -EPERM; @@ -300,9 +335,45 @@ static int drbd_adm_prepare(struct drbd_config_context= *adm_ctx, return err; } =20 -static int drbd_adm_finish(struct drbd_config_context *adm_ctx, - struct genl_info *info, int retcode) +static 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 =3D info->genlhdr->cmd; + unsigned int flags; + int err; + + adm_ctx =3D kzalloc_obj(*adm_ctx); + if (!adm_ctx) + return -ENOMEM; + + flags =3D (cmd < ARRAY_SIZE(drbd_genl_cmd_flags)) + ? drbd_genl_cmd_flags[cmd] : 0; + + err =3D drbd_adm_prepare(adm_ctx, skb, info, flags); + if (err && !adm_ctx->reply_skb) { + /* Fatal error before reply_skb was allocated. */ + kfree(adm_ctx); + return err; + } + if (err) + adm_ctx->reply_dh->ret_code =3D err; + + info->user_ptr[0] =3D adm_ctx; + return 0; +} + +static void drbd_post_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) +{ + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; + + if (!adm_ctx) + return; + + if (adm_ctx->reply_skb) + drbd_adm_send_reply(adm_ctx->reply_skb, info); + if (adm_ctx->device) { kref_put(&adm_ctx->device->kref, drbd_destroy_device); adm_ctx->device =3D NULL; @@ -316,12 +387,7 @@ static int drbd_adm_finish(struct drbd_config_context = *adm_ctx, adm_ctx->resource =3D NULL; } =20 - if (!adm_ctx->reply_skb) - return -ENOMEM; - - adm_ctx->reply_dh->ret_code =3D retcode; - drbd_adm_send_reply(adm_ctx->reply_skb, info); - return 0; + kfree(adm_ctx); } =20 static void setup_khelper_env(struct drbd_connection *connection, char **e= nvp) @@ -766,15 +832,15 @@ static const char *from_attrs_err_to_txt(int err) =20 int drbd_adm_set_role(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct set_role_parms parms; int err; enum drbd_ret_code retcode; enum drbd_state_rv rv; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 @@ -783,24 +849,24 @@ int drbd_adm_set_role(struct sk_buff *skb, struct gen= l_info *info) err =3D set_role_parms_from_attrs(&parms, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto out; } } genl_unlock(); - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); =20 if (info->genlhdr->cmd =3D=3D DRBD_ADM_PRIMARY) - rv =3D drbd_set_role(adm_ctx.device, R_PRIMARY, parms.assume_uptodate); + rv =3D drbd_set_role(adm_ctx->device, R_PRIMARY, parms.assume_uptodate); else - rv =3D drbd_set_role(adm_ctx.device, R_SECONDARY, 0); + rv =3D drbd_set_role(adm_ctx->device, R_SECONDARY, 0); =20 - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); genl_lock(); - drbd_adm_finish(&adm_ctx, info, rv); + adm_ctx->reply_dh->ret_code =3D rv; return 0; out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -1512,7 +1578,7 @@ static int disk_opts_check_al_size(struct drbd_device= *device, struct disk_conf =20 int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct drbd_device *device; struct disk_conf *new_disk_conf, *old_disk_conf; @@ -1520,14 +1586,14 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct = genl_info *info) int err; unsigned int fifo_size; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; =20 - device =3D adm_ctx.device; - mutex_lock(&adm_ctx.resource->adm_mutex); + device =3D adm_ctx->device; + mutex_lock(&adm_ctx->resource->adm_mutex); =20 /* we also need a disk * to change the options on */ @@ -1551,7 +1617,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct ge= nl_info *info) err =3D disk_conf_from_attrs_for_change(new_disk_conf, info); if (err && err !=3D -ENOMSG) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail_unlock; } =20 @@ -1577,7 +1643,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct ge= nl_info *info) if (err) { /* Could be just "busy". Ignore? * Introduce dedicated error code? */ - drbd_msg_put_info(adm_ctx.reply_skb, + drbd_msg_put_info(adm_ctx->reply_skb, "Try again without changing current al-extents setting"); retcode =3D ERR_NOMEM; goto fail_unlock; @@ -1640,9 +1706,9 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct ge= nl_info *info) success: put_ldev(device); out: - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -1734,7 +1800,7 @@ void drbd_backing_dev_free(struct drbd_device *device= , struct drbd_backing_dev * =20 int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_device *device; struct drbd_peer_device *peer_device; struct drbd_connection *connection; @@ -1751,14 +1817,14 @@ int drbd_adm_attach(struct sk_buff *skb, struct gen= l_info *info) enum drbd_state_rv rv; struct net_conf *nc; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; =20 - device =3D adm_ctx.device; - mutex_lock(&adm_ctx.resource->adm_mutex); + device =3D adm_ctx->device; + mutex_lock(&adm_ctx->resource->adm_mutex); peer_device =3D first_peer_device(device); connection =3D peer_device->connection; conn_reconfig_start(connection); @@ -1803,7 +1869,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_= info *info) err =3D disk_conf_from_attrs(new_disk_conf, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } =20 @@ -1954,7 +2020,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_= info *info) drbd_warn(device, "truncating a consistent device during attach (%llu <= %llu)\n", nsz, eff); } else { drbd_warn(device, "refusing to truncate a consistent device (%llu < %ll= u)\n", nsz, eff); - drbd_msg_sprintf_info(adm_ctx.reply_skb, + drbd_msg_sprintf_info(adm_ctx->reply_skb, "To-be-attached device has last effective > current size, and is consi= stent\n" "(%llu > %llu sectors). Refusing to attach.", eff, nsz); retcode =3D ERR_IMPLICIT_SHRINK; @@ -2130,8 +2196,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_= info *info) kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE); put_ldev(device); conn_reconfig_done(connection); - mutex_unlock(&adm_ctx.resource->adm_mutex); - drbd_adm_finish(&adm_ctx, info, retcode); + mutex_unlock(&adm_ctx->resource->adm_mutex); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; =20 force_diskless_dec: @@ -2150,9 +2216,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_= info *info) kfree(new_disk_conf); lc_destroy(resync_lru); kfree(new_plan); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -2174,14 +2240,14 @@ static int adm_detach(struct drbd_device *device, i= nt force) * Only then we have finally detached. */ int drbd_adm_detach(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct detach_parms parms =3D { }; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 @@ -2189,16 +2255,16 @@ int drbd_adm_detach(struct sk_buff *skb, struct gen= l_info *info) err =3D detach_parms_from_attrs(&parms, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto out; } } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - retcode =3D adm_detach(adm_ctx.device, parms.force_detach); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); + retcode =3D adm_detach(adm_ctx->device, parms.force_detach); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -2372,7 +2438,7 @@ static void free_crypto(struct crypto *crypto) =20 int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct drbd_connection *connection; struct net_conf *old_net_conf, *new_net_conf =3D NULL; @@ -2381,14 +2447,14 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct g= enl_info *info) int rsr; /* re-sync running */ struct crypto crypto =3D { }; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_CONNECTIO= N); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; =20 - connection =3D adm_ctx.connection; - mutex_lock(&adm_ctx.resource->adm_mutex); + connection =3D adm_ctx->connection; + mutex_lock(&adm_ctx->resource->adm_mutex); =20 new_net_conf =3D kzalloc_obj(struct net_conf); if (!new_net_conf) { @@ -2403,7 +2469,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct gen= l_info *info) old_net_conf =3D connection->net_conf; =20 if (!old_net_conf) { - drbd_msg_put_info(adm_ctx.reply_skb, "net conf missing, try connect"); + drbd_msg_put_info(adm_ctx->reply_skb, "net conf missing, try connect"); retcode =3D ERR_INVALID_REQUEST; goto fail; } @@ -2415,7 +2481,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct gen= l_info *info) err =3D net_conf_from_attrs_for_change(new_net_conf, info); if (err && err !=3D -ENOMSG) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } =20 @@ -2485,9 +2551,9 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct gen= l_info *info) done: conn_reconfig_done(connection); out: - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -2516,7 +2582,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) struct connection_info connection_info; enum drbd_notification_type flags; unsigned int peer_devices =3D 0; - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_peer_device *peer_device; struct net_conf *old_net_conf, *new_net_conf =3D NULL; struct crypto crypto =3D { }; @@ -2527,14 +2593,13 @@ int drbd_adm_connect(struct sk_buff *skb, struct ge= nl_info *info) int i; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE); - - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; - if (!(adm_ctx.my_addr && adm_ctx.peer_addr)) { - drbd_msg_put_info(adm_ctx.reply_skb, "connection endpoint(s) missing"); + if (!(adm_ctx->my_addr && adm_ctx->peer_addr)) { + drbd_msg_put_info(adm_ctx->reply_skb, "connection endpoint(s) missing"); retcode =3D ERR_INVALID_REQUEST; goto out; } @@ -2544,15 +2609,15 @@ int drbd_adm_connect(struct sk_buff *skb, struct ge= nl_info *info) * concurrent reconfiguration/addition/deletion */ for_each_resource(resource, &drbd_resources) { for_each_connection(connection, resource) { - if (nla_len(adm_ctx.my_addr) =3D=3D connection->my_addr_len && - !memcmp(nla_data(adm_ctx.my_addr), &connection->my_addr, + if (nla_len(adm_ctx->my_addr) =3D=3D connection->my_addr_len && + !memcmp(nla_data(adm_ctx->my_addr), &connection->my_addr, connection->my_addr_len)) { retcode =3D ERR_LOCAL_ADDR; goto out; } =20 - if (nla_len(adm_ctx.peer_addr) =3D=3D connection->peer_addr_len && - !memcmp(nla_data(adm_ctx.peer_addr), &connection->peer_addr, + if (nla_len(adm_ctx->peer_addr) =3D=3D connection->peer_addr_len && + !memcmp(nla_data(adm_ctx->peer_addr), &connection->peer_addr, connection->peer_addr_len)) { retcode =3D ERR_PEER_ADDR; goto out; @@ -2560,8 +2625,8 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) } } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - connection =3D first_connection(adm_ctx.resource); + mutex_lock(&adm_ctx->resource->adm_mutex); + connection =3D first_connection(adm_ctx->resource); conn_reconfig_start(connection); =20 if (connection->cstate > C_STANDALONE) { @@ -2581,7 +2646,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) err =3D net_conf_from_attrs(new_net_conf, info); if (err && err !=3D -ENOMSG) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } =20 @@ -2597,11 +2662,11 @@ int drbd_adm_connect(struct sk_buff *skb, struct ge= nl_info *info) =20 drbd_flush_workqueue(&connection->sender_work); =20 - mutex_lock(&adm_ctx.resource->conf_update); + mutex_lock(&adm_ctx->resource->conf_update); old_net_conf =3D connection->net_conf; if (old_net_conf) { retcode =3D ERR_NET_CONFIGURED; - mutex_unlock(&adm_ctx.resource->conf_update); + mutex_unlock(&adm_ctx->resource->conf_update); goto fail; } rcu_assign_pointer(connection->net_conf, new_net_conf); @@ -2612,10 +2677,10 @@ int drbd_adm_connect(struct sk_buff *skb, struct ge= nl_info *info) connection->csums_tfm =3D crypto.csums_tfm; connection->verify_tfm =3D crypto.verify_tfm; =20 - connection->my_addr_len =3D nla_len(adm_ctx.my_addr); - memcpy(&connection->my_addr, nla_data(adm_ctx.my_addr), connection->my_ad= dr_len); - connection->peer_addr_len =3D nla_len(adm_ctx.peer_addr); - memcpy(&connection->peer_addr, nla_data(adm_ctx.peer_addr), connection->p= eer_addr_len); + connection->my_addr_len =3D nla_len(adm_ctx->my_addr); + memcpy(&connection->my_addr, nla_data(adm_ctx->my_addr), connection->my_a= ddr_len); + connection->peer_addr_len =3D nla_len(adm_ctx->peer_addr); + memcpy(&connection->peer_addr, nla_data(adm_ctx->peer_addr), connection->= peer_addr_len); =20 idr_for_each_entry(&connection->peer_devices, peer_device, i) { peer_devices++; @@ -2633,7 +2698,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) notify_peer_device_state(NULL, 0, peer_device, &peer_device_info, NOTIFY= _CREATE | flags); } mutex_unlock(¬ification_mutex); - mutex_unlock(&adm_ctx.resource->conf_update); + mutex_unlock(&adm_ctx->resource->conf_update); =20 rcu_read_lock(); idr_for_each_entry(&connection->peer_devices, peer_device, i) { @@ -2646,8 +2711,8 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) rv =3D conn_request_state(connection, NS(conn, C_UNCONNECTED), CS_VERBOSE= ); =20 conn_reconfig_done(connection); - mutex_unlock(&adm_ctx.resource->adm_mutex); - drbd_adm_finish(&adm_ctx, info, rv); + mutex_unlock(&adm_ctx->resource->adm_mutex); + adm_ctx->reply_dh->ret_code =3D rv; return 0; =20 fail: @@ -2655,9 +2720,9 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl= _info *info) kfree(new_net_conf); =20 conn_reconfig_done(connection); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -2729,40 +2794,40 @@ static enum drbd_state_rv conn_try_disconnect(struc= t drbd_connection *connection =20 int drbd_adm_disconnect(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct disconnect_parms parms; struct drbd_connection *connection; enum drbd_state_rv rv; enum drbd_ret_code retcode; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_CONNECTIO= N); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto fail; =20 - connection =3D adm_ctx.connection; + connection =3D adm_ctx->connection; memset(&parms, 0, sizeof(parms)); if (info->attrs[DRBD_NLA_DISCONNECT_PARMS]) { err =3D disconnect_parms_from_attrs(&parms, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); rv =3D conn_try_disconnect(connection, parms.force_disconnect); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); if (rv < SS_SUCCESS) { - drbd_adm_finish(&adm_ctx, info, rv); + adm_ctx->reply_dh->ret_code =3D rv; return 0; } retcode =3D NO_ERROR; fail: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -2784,7 +2849,7 @@ void resync_after_online_grow(struct drbd_device *dev= ice) =20 int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct disk_conf *old_disk_conf, *new_disk_conf =3D NULL; struct resize_parms rs; struct drbd_device *device; @@ -2795,14 +2860,14 @@ int drbd_adm_resize(struct sk_buff *skb, struct gen= l_info *info) sector_t u_size; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - device =3D adm_ctx.device; + mutex_lock(&adm_ctx->resource->adm_mutex); + device =3D adm_ctx->device; if (!get_ldev(device)) { retcode =3D ERR_NO_DISK; goto fail; @@ -2815,7 +2880,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_= info *info) err =3D resize_parms_from_attrs(&rs, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail_ldev; } } @@ -2907,9 +2972,9 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_= info *info) } =20 fail: - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; =20 fail_ldev: @@ -2920,61 +2985,61 @@ int drbd_adm_resize(struct sk_buff *skb, struct gen= l_info *info) =20 int drbd_adm_resource_opts(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct res_opts res_opts; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto fail; =20 - res_opts =3D adm_ctx.resource->res_opts; + res_opts =3D adm_ctx->resource->res_opts; if (should_set_defaults(info)) set_res_opts_defaults(&res_opts); =20 err =3D res_opts_from_attrs(&res_opts, info); if (err && err !=3D -ENOMSG) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto fail; } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - err =3D set_resource_options(adm_ctx.resource, &res_opts); + mutex_lock(&adm_ctx->resource->adm_mutex); + err =3D set_resource_options(adm_ctx->resource, &res_opts); if (err) { retcode =3D ERR_INVALID_REQUEST; if (err =3D=3D -ENOMEM) retcode =3D ERR_NOMEM; } - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); =20 fail: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_device *device; int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */ =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - device =3D adm_ctx.device; + device =3D adm_ctx->device; if (!get_ldev(device)) { retcode =3D ERR_NO_DISK; goto out; } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); =20 /* If there is still bitmap IO pending, probably because of a previous * resync just being finished, wait for it before requesting a new resync. @@ -2997,30 +3062,30 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct= genl_info *info) } else retcode =3D drbd_request_state(device, NS(conn, C_STARTING_SYNC_T)); drbd_resume_io(device); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); put_ldev(device); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 static int drbd_adm_simple_request_state(struct sk_buff *skb, struct genl_= info *info, union drbd_state mask, union drbd_state val) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - retcode =3D drbd_request_state(adm_ctx.device, mask, val); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); + retcode =3D drbd_request_state(adm_ctx->device, mask, val); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -3036,23 +3101,23 @@ static int drbd_bmio_set_susp_al(struct drbd_device= *device, =20 int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; int retcode; /* drbd_ret_code, drbd_state_rv */ struct drbd_device *device; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - device =3D adm_ctx.device; + device =3D adm_ctx->device; if (!get_ldev(device)) { retcode =3D ERR_NO_DISK; goto out; } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); =20 /* If there is still bitmap IO pending, probably because of a previous * resync just being finished, wait for it before requesting a new resync. @@ -3078,48 +3143,48 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, s= truct genl_info *info) } else retcode =3D drbd_request_state(device, NS(conn, C_STARTING_SYNC_S)); drbd_resume_io(device); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); put_ldev(device); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 int drbd_adm_pause_sync(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - if (drbd_request_state(adm_ctx.device, NS(user_isp, 1)) =3D=3D SS_NOTHING= _TO_DO) + mutex_lock(&adm_ctx->resource->adm_mutex); + if (drbd_request_state(adm_ctx->device, NS(user_isp, 1)) =3D=3D SS_NOTHIN= G_TO_DO) retcode =3D ERR_PAUSE_IS_SET; - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 int drbd_adm_resume_sync(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; union drbd_dev_state s; enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - if (drbd_request_state(adm_ctx.device, NS(user_isp, 0)) =3D=3D SS_NOTHING= _TO_DO) { - s =3D adm_ctx.device->state; + mutex_lock(&adm_ctx->resource->adm_mutex); + if (drbd_request_state(adm_ctx->device, NS(user_isp, 0)) =3D=3D SS_NOTHIN= G_TO_DO) { + s =3D adm_ctx->device->state; if (s.conn =3D=3D C_PAUSED_SYNC_S || s.conn =3D=3D C_PAUSED_SYNC_T) { retcode =3D s.aftr_isp ? ERR_PIC_AFTER_DEP : s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR; @@ -3127,9 +3192,9 @@ int drbd_adm_resume_sync(struct sk_buff *skb, struct = genl_info *info) retcode =3D ERR_PAUSE_IS_CLEAR; } } - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -3140,18 +3205,18 @@ int drbd_adm_suspend_io(struct sk_buff *skb, struct= genl_info *info) =20 int drbd_adm_resume_io(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_device *device; int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */ =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - device =3D adm_ctx.device; + mutex_lock(&adm_ctx->resource->adm_mutex); + device =3D adm_ctx->device; if (test_bit(NEW_CUR_UUID, &device->flags)) { if (get_ldev_if_state(device, D_ATTACHING)) { drbd_uuid_new_current(device); @@ -3188,9 +3253,9 @@ int drbd_adm_resume_io(struct sk_buff *skb, struct ge= nl_info *info) tl_restart(first_peer_device(device)->connection, FAIL_FROZEN_DISK_IO); } drbd_resume_io(device); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -3843,23 +3908,24 @@ static int nla_put_status_info(struct sk_buff *skb,= struct drbd_device *device, =20 int drbd_adm_get_status(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - err =3D nla_put_status_info(adm_ctx.reply_skb, adm_ctx.device, NULL); + err =3D nla_put_status_info(adm_ctx->reply_skb, adm_ctx->device, NULL); if (err) { - nlmsg_free(adm_ctx.reply_skb); + nlmsg_free(adm_ctx->reply_skb); + adm_ctx->reply_skb =3D NULL; return err; } out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -4046,46 +4112,47 @@ int drbd_adm_get_status_all(struct sk_buff *skb, st= ruct netlink_callback *cb) =20 int drbd_adm_get_timeout_type(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct timeout_parms tp; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 tp.timeout_type =3D - adm_ctx.device->state.pdsk =3D=3D D_OUTDATED ? UT_PEER_OUTDATED : - test_bit(USE_DEGR_WFC_T, &adm_ctx.device->flags) ? UT_DEGRADED : + adm_ctx->device->state.pdsk =3D=3D D_OUTDATED ? UT_PEER_OUTDATED : + test_bit(USE_DEGR_WFC_T, &adm_ctx->device->flags) ? UT_DEGRADED : UT_DEFAULT; =20 - err =3D timeout_parms_to_priv_skb(adm_ctx.reply_skb, &tp); + err =3D timeout_parms_to_priv_skb(adm_ctx->reply_skb, &tp); if (err) { - nlmsg_free(adm_ctx.reply_skb); + nlmsg_free(adm_ctx->reply_skb); + adm_ctx->reply_skb =3D NULL; return err; } out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 int drbd_adm_start_ov(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_device *device; enum drbd_ret_code retcode; struct start_ov_parms parms; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - device =3D adm_ctx.device; + device =3D adm_ctx->device; =20 /* resume from last known position, if possible */ parms.ov_start_sector =3D device->ov_start_sector; @@ -4094,11 +4161,11 @@ int drbd_adm_start_ov(struct sk_buff *skb, struct g= enl_info *info) int err =3D start_ov_parms_from_attrs(&parms, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto out; } } - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); =20 /* w_make_ov_request expects position to be aligned */ device->ov_start_sector =3D parms.ov_start_sector & ~(BM_SECT_PER_BIT-1); @@ -4111,40 +4178,40 @@ int drbd_adm_start_ov(struct sk_buff *skb, struct g= enl_info *info) retcode =3D drbd_request_state(device, NS(conn, C_VERIFY_S)); drbd_resume_io(device); =20 - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 =20 int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_device *device; enum drbd_ret_code retcode; int skip_initial_sync =3D 0; int err; struct new_c_uuid_parms args; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out_nolock; =20 - device =3D adm_ctx.device; + device =3D adm_ctx->device; memset(&args, 0, sizeof(args)); if (info->attrs[DRBD_NLA_NEW_C_UUID_PARMS]) { err =3D new_c_uuid_parms_from_attrs(&args, info); if (err) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto out_nolock; } } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); mutex_lock(device->state_mutex); /* Protects us against serialized state = changes. */ =20 if (!get_ldev(device)) { @@ -4189,9 +4256,9 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct g= enl_info *info) put_ldev(device); out: mutex_unlock(device->state_mutex); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out_nolock: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -4224,14 +4291,14 @@ static void resource_to_info(struct resource_info *= info, int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info) { struct drbd_connection *connection; - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; struct res_opts res_opts; int err; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, 0); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 @@ -4239,18 +4306,18 @@ int drbd_adm_new_resource(struct sk_buff *skb, stru= ct genl_info *info) err =3D res_opts_from_attrs(&res_opts, info); if (err && err !=3D -ENOMSG) { retcode =3D ERR_MANDATORY_TAG; - drbd_msg_put_info(adm_ctx.reply_skb, from_attrs_err_to_txt(err)); + drbd_msg_put_info(adm_ctx->reply_skb, from_attrs_err_to_txt(err)); goto out; } =20 - retcode =3D drbd_check_resource_name(&adm_ctx); + retcode =3D drbd_check_resource_name(adm_ctx); if (retcode !=3D NO_ERROR) goto out; =20 - if (adm_ctx.resource) { + if (adm_ctx->resource) { if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) { retcode =3D ERR_INVALID_REQUEST; - drbd_msg_put_info(adm_ctx.reply_skb, "resource exists"); + drbd_msg_put_info(adm_ctx->reply_skb, "resource exists"); } /* else: still NO_ERROR */ goto out; @@ -4258,7 +4325,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct= genl_info *info) =20 /* not yet safe for genl_family.parallel_ops */ mutex_lock(&resources_mutex); - connection =3D conn_create(adm_ctx.resource_name, &res_opts); + connection =3D conn_create(adm_ctx->resource_name, &res_opts); mutex_unlock(&resources_mutex); =20 if (connection) { @@ -4273,7 +4340,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct= genl_info *info) retcode =3D ERR_NOMEM; =20 out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -4286,38 +4353,38 @@ static void device_to_info(struct device_info *info, =20 int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_genlmsghdr *dh =3D genl_info_userhdr(info); enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 if (dh->minor > MINORMASK) { - drbd_msg_put_info(adm_ctx.reply_skb, "requested minor out of range"); + drbd_msg_put_info(adm_ctx->reply_skb, "requested minor out of range"); retcode =3D ERR_INVALID_REQUEST; goto out; } - if (adm_ctx.volume > DRBD_VOLUME_MAX) { - drbd_msg_put_info(adm_ctx.reply_skb, "requested volume id out of range"); + if (adm_ctx->volume > DRBD_VOLUME_MAX) { + drbd_msg_put_info(adm_ctx->reply_skb, "requested volume id out of range"= ); retcode =3D ERR_INVALID_REQUEST; goto out; } =20 /* drbd_adm_prepare made sure already * that first_peer_device(device)->connection and device->vnr match the r= equest. */ - if (adm_ctx.device) { + if (adm_ctx->device) { if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) retcode =3D ERR_MINOR_OR_VOLUME_EXISTS; /* else: still NO_ERROR */ goto out; } =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - retcode =3D drbd_create_device(&adm_ctx, dh->minor); + mutex_lock(&adm_ctx->resource->adm_mutex); + retcode =3D drbd_create_device(adm_ctx, dh->minor); if (retcode =3D=3D NO_ERROR) { struct drbd_device *device; struct drbd_peer_device *peer_device; @@ -4348,9 +4415,9 @@ int drbd_adm_new_minor(struct sk_buff *skb, struct ge= nl_info *info) } mutex_unlock(¬ification_mutex); } - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -4393,20 +4460,20 @@ static enum drbd_ret_code adm_del_minor(struct drbd= _device *device) =20 int drbd_adm_del_minor(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_MINOR); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto out; =20 - mutex_lock(&adm_ctx.resource->adm_mutex); - retcode =3D adm_del_minor(adm_ctx.device); - mutex_unlock(&adm_ctx.resource->adm_mutex); + mutex_lock(&adm_ctx->resource->adm_mutex); + retcode =3D adm_del_minor(adm_ctx->device); + mutex_unlock(&adm_ctx->resource->adm_mutex); out: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 @@ -4442,20 +4509,20 @@ static int adm_del_resource(struct drbd_resource *r= esource) =20 int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_resource *resource; struct drbd_connection *connection; struct drbd_device *device; int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */ unsigned i; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; =20 - resource =3D adm_ctx.resource; + resource =3D adm_ctx->resource; mutex_lock(&resource->adm_mutex); /* demote */ for_each_connection(connection, resource) { @@ -4464,14 +4531,14 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_= info *info) idr_for_each_entry(&connection->peer_devices, peer_device, i) { retcode =3D drbd_set_role(peer_device->device, R_SECONDARY, 0); if (retcode < SS_SUCCESS) { - drbd_msg_put_info(adm_ctx.reply_skb, "failed to demote"); + drbd_msg_put_info(adm_ctx->reply_skb, "failed to demote"); goto out; } } =20 retcode =3D conn_try_disconnect(connection, 0); if (retcode < SS_SUCCESS) { - drbd_msg_put_info(adm_ctx.reply_skb, "failed to disconnect"); + drbd_msg_put_info(adm_ctx->reply_skb, "failed to disconnect"); goto out; } } @@ -4480,7 +4547,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_in= fo *info) idr_for_each_entry(&resource->devices, device, i) { retcode =3D adm_detach(device, 0); if (retcode < SS_SUCCESS || retcode > NO_ERROR) { - drbd_msg_put_info(adm_ctx.reply_skb, "failed to detach"); + drbd_msg_put_info(adm_ctx->reply_skb, "failed to detach"); goto out; } } @@ -4490,7 +4557,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_in= fo *info) retcode =3D adm_del_minor(device); if (retcode !=3D NO_ERROR) { /* "can not happen" */ - drbd_msg_put_info(adm_ctx.reply_skb, "failed to delete volume"); + drbd_msg_put_info(adm_ctx->reply_skb, "failed to delete volume"); goto out; } } @@ -4499,28 +4566,28 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_= info *info) out: mutex_unlock(&resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info) { - struct drbd_config_context adm_ctx; + struct drbd_config_context *adm_ctx =3D info->user_ptr[0]; struct drbd_resource *resource; enum drbd_ret_code retcode; =20 - retcode =3D drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE); - if (!adm_ctx.reply_skb) - return retcode; + if (!adm_ctx->reply_skb) + return 0; + retcode =3D adm_ctx->reply_dh->ret_code; if (retcode !=3D NO_ERROR) goto finish; - resource =3D adm_ctx.resource; + resource =3D adm_ctx->resource; =20 mutex_lock(&resource->adm_mutex); retcode =3D adm_del_resource(resource); mutex_unlock(&resource->adm_mutex); finish: - drbd_adm_finish(&adm_ctx, info, retcode); + adm_ctx->reply_dh->ret_code =3D retcode; return 0; } =20 diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_fun= c.h index d4da060b7532..6edcac85155e 100644 --- a/include/linux/genl_magic_func.h +++ b/include/linux/genl_magic_func.h @@ -292,6 +292,10 @@ static struct genl_family ZZZ_genl_family __ro_after_i= nit =3D { #endif .maxattr =3D ARRAY_SIZE(CONCATENATE(GENL_MAGIC_FAMILY, _tla_nl_policy))-1, .policy =3D CONCATENATE(GENL_MAGIC_FAMILY, _tla_nl_policy), +#ifdef GENL_MAGIC_FAMILY_PRE_DOIT + .pre_doit =3D GENL_MAGIC_FAMILY_PRE_DOIT, + .post_doit =3D GENL_MAGIC_FAMILY_POST_DOIT, +#endif .ops =3D ZZZ_genl_ops, .n_ops =3D ARRAY_SIZE(ZZZ_genl_ops), .mcgrps =3D ZZZ_genl_mcgrps, base-commit: 67807fbaf12719fca46a622d759484652b79c7c3 --=20 2.53.0