* Re: [PATCH 2/2] selftests: ublk: test that teardown after incomplete recovery completes
From: Ming Lei @ 2026-04-04 13:33 UTC (permalink / raw)
To: Uday Shankar
Cc: Caleb Sander Mateos, Jens Axboe, Shuah Khan, linux-block,
linux-kernel, linux-kselftest
In-Reply-To: <20260403-cancel-v1-2-86e5a6b3d3af@purestorage.com>
On Fri, Apr 03, 2026 at 09:23:56PM -0600, Uday Shankar wrote:
> Before the fix, teardown of a ublk server that was attempting to recover
> a device, but died when it had submitted a nonempty proper subset of the
> fetch commands to any queue would loop forever. Add a test to verify
> that, after the fix, teardown completes. This is done by:
>
> - Adding a new argument to the fault_inject target that causes it die
> after fetching a nonempty proper subset of the IOs to a queue
> - Using that argument in a new test while trying to recover an
> already-created device
> - Attempting to delete the ublk device at the end of the test; this
> hangs forever if teardown from the fault-injected ublk server never
> completed.
>
> It was manually verified that the test passes with the fix and hangs
> without it.
>
> Signed-off-by: Uday Shankar <ushankar@purestorage.com>
> ---
> tools/testing/selftests/ublk/Makefile | 1 +
> tools/testing/selftests/ublk/fault_inject.c | 51 +++++++++++++++++++++++--
> tools/testing/selftests/ublk/kublk.c | 4 ++
> tools/testing/selftests/ublk/kublk.h | 3 ++
> tools/testing/selftests/ublk/test_generic_17.sh | 35 +++++++++++++++++
> 5 files changed, 91 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
> index 8ac2d4a682a1768fb1eb9d2dd2a5d01294a67a03..d338668c5a5fbd73f6d70165455a3551ab13e894 100644
> --- a/tools/testing/selftests/ublk/Makefile
> +++ b/tools/testing/selftests/ublk/Makefile
> @@ -18,6 +18,7 @@ TEST_PROGS += test_generic_10.sh
> TEST_PROGS += test_generic_12.sh
> TEST_PROGS += test_generic_13.sh
> TEST_PROGS += test_generic_16.sh
> +TEST_PROGS += test_generic_17.sh
>
> TEST_PROGS += test_batch_01.sh
> TEST_PROGS += test_batch_02.sh
> diff --git a/tools/testing/selftests/ublk/fault_inject.c b/tools/testing/selftests/ublk/fault_inject.c
> index 3b897f69c014cc73b4b469d816e80284dd21b577..228a9605053409c84baaf255f97c4abc271a8bfd 100644
> --- a/tools/testing/selftests/ublk/fault_inject.c
> +++ b/tools/testing/selftests/ublk/fault_inject.c
> @@ -10,11 +10,17 @@
>
> #include "kublk.h"
>
> +struct fi_opts {
> + long long delay_ns;
> + bool die_during_fetch;
> +};
> +
> static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
> struct ublk_dev *dev)
> {
> const struct ublksrv_ctrl_dev_info *info = &dev->dev_info;
> unsigned long dev_size = 250UL << 30;
> + struct fi_opts *opts = NULL;
>
> if (ctx->auto_zc_fallback) {
> ublk_err("%s: not support auto_zc_fallback\n", __func__);
> @@ -35,17 +41,51 @@ static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
> };
> ublk_set_integrity_params(ctx, &dev->tgt.params);
>
> - dev->private_data = (void *)(unsigned long)(ctx->fault_inject.delay_us * 1000);
> + opts = calloc(1, sizeof(*opts));
> + if (!opts) {
> + ublk_err("%s: couldn't allocate memory for opts\n", __func__);
> + return -ENOMEM;
> + }
> +
> + opts->delay_ns = ctx->fault_inject.delay_us * 1000;
> + opts->die_during_fetch = ctx->fault_inject.die_during_fetch;
> + dev->private_data = opts;
> +
> return 0;
> }
>
> +static void ublk_fault_inject_pre_fetch_io(struct ublk_thread *t,
> + struct ublk_queue *q, int tag)
> +{
> + struct fi_opts *opts = q->dev->private_data;
> +
> + if (!opts->die_during_fetch)
> + return;
> +
> + /*
> + * Each queue fetches its IOs in increasing order of tags, so
> + * dying just before we're about to fetch tag 1 (regardless of
> + * what queue we're on) guarantees that we've fetched a nonempty
> + * proper subset of the tags on that queue.
> + */
> + if (tag == 1) {
> + /*
> + * Ensure our commands are actually live in the kernel
> + * before we die.
> + */
> + io_uring_submit(&t->ring);
> + raise(SIGKILL);
> + }
> +}
> +
> static int ublk_fault_inject_queue_io(struct ublk_thread *t,
> struct ublk_queue *q, int tag)
> {
> const struct ublksrv_io_desc *iod = ublk_get_iod(q, tag);
> struct io_uring_sqe *sqe;
> + struct fi_opts *opts = q->dev->private_data;
> struct __kernel_timespec ts = {
> - .tv_nsec = (long long)q->dev->private_data,
> + .tv_nsec = opts->delay_ns,
> };
>
> ublk_io_alloc_sqes(t, &sqe, 1);
> @@ -77,29 +117,34 @@ static void ublk_fault_inject_cmd_line(struct dev_ctx *ctx, int argc, char *argv
> {
> static const struct option longopts[] = {
> { "delay_us", 1, NULL, 0 },
> + { "die_during_fetch", 1, NULL, 0 },
> { 0, 0, 0, 0 }
> };
> int option_idx, opt;
>
> ctx->fault_inject.delay_us = 0;
> + ctx->fault_inject.die_during_fetch = false;
> while ((opt = getopt_long(argc, argv, "",
> longopts, &option_idx)) != -1) {
> switch (opt) {
> case 0:
> if (!strcmp(longopts[option_idx].name, "delay_us"))
> ctx->fault_inject.delay_us = strtoll(optarg, NULL, 10);
> + if (!strcmp(longopts[option_idx].name, "die_during_fetch"))
> + ctx->fault_inject.die_during_fetch = strtoll(optarg, NULL, 10);
> }
> }
> }
>
> static void ublk_fault_inject_usage(const struct ublk_tgt_ops *ops)
> {
> - printf("\tfault_inject: [--delay_us us (default 0)]\n");
> + printf("\tfault_inject: [--delay_us us (default 0)] [--die_during_fetch 1]\n");
> }
>
> const struct ublk_tgt_ops fault_inject_tgt_ops = {
> .name = "fault_inject",
> .init_tgt = ublk_fault_inject_tgt_init,
> + .pre_fetch_io = ublk_fault_inject_pre_fetch_io,
> .queue_io = ublk_fault_inject_queue_io,
> .tgt_io_done = ublk_fault_inject_tgt_io_done,
> .parse_cmd_line = ublk_fault_inject_cmd_line,
> diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
> index e1c3b3c55e565c8cad6b6fe9b9b764cd244818c0..8260c96a39c05584065f41a52f3d9050614454c6 100644
> --- a/tools/testing/selftests/ublk/kublk.c
> +++ b/tools/testing/selftests/ublk/kublk.c
> @@ -796,6 +796,8 @@ static void ublk_submit_fetch_commands(struct ublk_thread *t)
> q = &t->dev->q[q_id];
> io = &q->ios[tag];
> io->buf_index = j++;
> + if (q->tgt_ops->pre_fetch_io)
> + q->tgt_ops->pre_fetch_io(t, q, tag);
> ublk_queue_io_cmd(t, io);
> }
> } else {
> @@ -807,6 +809,8 @@ static void ublk_submit_fetch_commands(struct ublk_thread *t)
> for (i = 0; i < q->q_depth; i++) {
> io = &q->ios[i];
> io->buf_index = i;
> + if (q->tgt_ops->pre_fetch_io)
> + q->tgt_ops->pre_fetch_io(t, q, i);
> ublk_queue_io_cmd(t, io);
> }
> }
The callback needs to be called in ublk_batch_setup_queues() for F_BATCH
too.
Otherwise, this patch looks good.
Thanks,
Ming
^ permalink raw reply
* Re: [PATCH 1/2] ublk: reset per-IO canceled flag on each fetch
From: Ming Lei @ 2026-04-04 13:28 UTC (permalink / raw)
To: Uday Shankar
Cc: Caleb Sander Mateos, Jens Axboe, Shuah Khan, linux-block,
linux-kernel, linux-kselftest
In-Reply-To: <20260403-cancel-v1-1-86e5a6b3d3af@purestorage.com>
On Fri, Apr 03, 2026 at 09:23:55PM -0600, Uday Shankar wrote:
> If a ublk server starts recovering devices but dies before issuing fetch
> commands for all IOs, cancellation of the fetch commands that were
> successfully issued may never complete. This is because the per-IO
> canceled flag can remain set even after the fetch for that IO has been
> submitted - the per-IO canceled flags for all IOs in a queue are reset
> together only once all IOs for that queue have been fetched. So if a
> nonempty proper subset of the IOs for a queue are fetched when the ublk
> server dies, the IOs in that subset will never successfully be canceled,
> as their canceled flags remain set, and this prevents ublk_cancel_cmd
> from actually calling io_uring_cmd_done on the commands, despite the
> fact that they are outstanding.
>
> Fix this by resetting the per-IO cancel flags immediately when each IO
> is fetched instead of waiting for all IOs for the queue (which may never
> happen).
>
> Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Fixes: 728cbac5fe21 ("ublk: move device reset into ublk_ch_release()")
Reviewed-by: Ming Lei <ming.lei@redhat.com>
thanks,
Ming
^ permalink raw reply
* Re: [PATCH blktests] src/dio-offsets.c: Fix err() usage
From: Shinichiro Kawasaki @ 2026-04-04 8:35 UTC (permalink / raw)
To: Bart Van Assche; +Cc: Damien Le Moal, linux-block@vger.kernel.org, Keith Busch
In-Reply-To: <20260326173632.3259254-1-bvanassche@acm.org>
On Mar 26, 2026 / 10:36, Bart Van Assche wrote:
> If the dio-offsets program detects data corruption, it reports the
> following message:
>
> dio-offsets: test_unaligned_vectors: data corruption: Success
>
> The "Success" part in this message is confusing and is reported because
> the err() macro is used incorrectly. errno must be set before err() is
> used instead of passing an error number as first argument. Fix usage of
> the err() macro as follows:
> - Change the first argument into EXIT_FAILURE (1). According to POSIX,
> exit codes 1 - 125 mean failure and > 128 means that a program was
> terminated by a signal. Hence, exit with code 1 instead of -1 if
> ioctl() fails.
> - Use the err_errno() macro to set the error code instead of passing an
> error code as first argument to err().
Bart, thanks for the patch. Overall, it looks good to me.
One thing I found is that one more err(EIO,...) is left in __compare() after
applying the patch. Should we convert it also into err_errno()? If so, I will
fold-in the hunk below.
diff --git a/src/dio-offsets.c b/src/dio-offsets.c
index 9fc7b92..c40ce68 100644
--- a/src/dio-offsets.c
+++ b/src/dio-offsets.c
@@ -131,7 +131,7 @@ static void __compare(void *a, void *b, size_t size, const char *test)
{
if (!memcmp(a, b, size))
return;
- err(EIO, "%s: data corruption", test);
+ err_errno(EIO, "%s: data corruption", test);
}
#define compare(a, b, size) __compare(a, b, size, __func__)
^ permalink raw reply related
* Re: [PATCH blktests 0/7] Skip tests if scsi_debug module is already loaded and in use
From: Shinichiro Kawasaki @ 2026-04-04 8:06 UTC (permalink / raw)
To: linux-block@vger.kernel.org; +Cc: disgoel@linux.ibm.com
In-Reply-To: <20260324054949.3821569-1-shinichiro.kawasaki@wdc.com>
On Mar 24, 2026 / 14:49, Shin'ichiro Kawasaki wrote:
> When blktests users have scsi_debug devices configured for purposes other than
> blktests, running blktests currently unloads scsi_debug unconditionally and
> breaks the existing setup. To avoid disrupting such configurations, this patch
> series improves blktests to check whether the scsi_debug module is already
> loaded and in use, and to skip test cases that require scsi_debug in that
> situation.
>
> This series was originally proposed as a GitHub Pull Request [1]. Disha Goel and
> I worked on the patches. The first four patches fix pre-existing problems found
> while working on this series. The fifth patch implements the improvement
> described above. The last two patches fix two additional problems that were
> found during this work.
FYI, I applied this series.
^ permalink raw reply
* [PATCH 2/2] selftests: ublk: test that teardown after incomplete recovery completes
From: Uday Shankar @ 2026-04-04 3:23 UTC (permalink / raw)
To: Ming Lei, Caleb Sander Mateos, Jens Axboe, Shuah Khan
Cc: linux-block, linux-kernel, linux-kselftest, Uday Shankar
In-Reply-To: <20260403-cancel-v1-0-86e5a6b3d3af@purestorage.com>
Before the fix, teardown of a ublk server that was attempting to recover
a device, but died when it had submitted a nonempty proper subset of the
fetch commands to any queue would loop forever. Add a test to verify
that, after the fix, teardown completes. This is done by:
- Adding a new argument to the fault_inject target that causes it die
after fetching a nonempty proper subset of the IOs to a queue
- Using that argument in a new test while trying to recover an
already-created device
- Attempting to delete the ublk device at the end of the test; this
hangs forever if teardown from the fault-injected ublk server never
completed.
It was manually verified that the test passes with the fix and hangs
without it.
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
---
tools/testing/selftests/ublk/Makefile | 1 +
tools/testing/selftests/ublk/fault_inject.c | 51 +++++++++++++++++++++++--
tools/testing/selftests/ublk/kublk.c | 4 ++
tools/testing/selftests/ublk/kublk.h | 3 ++
tools/testing/selftests/ublk/test_generic_17.sh | 35 +++++++++++++++++
5 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index 8ac2d4a682a1768fb1eb9d2dd2a5d01294a67a03..d338668c5a5fbd73f6d70165455a3551ab13e894 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -18,6 +18,7 @@ TEST_PROGS += test_generic_10.sh
TEST_PROGS += test_generic_12.sh
TEST_PROGS += test_generic_13.sh
TEST_PROGS += test_generic_16.sh
+TEST_PROGS += test_generic_17.sh
TEST_PROGS += test_batch_01.sh
TEST_PROGS += test_batch_02.sh
diff --git a/tools/testing/selftests/ublk/fault_inject.c b/tools/testing/selftests/ublk/fault_inject.c
index 3b897f69c014cc73b4b469d816e80284dd21b577..228a9605053409c84baaf255f97c4abc271a8bfd 100644
--- a/tools/testing/selftests/ublk/fault_inject.c
+++ b/tools/testing/selftests/ublk/fault_inject.c
@@ -10,11 +10,17 @@
#include "kublk.h"
+struct fi_opts {
+ long long delay_ns;
+ bool die_during_fetch;
+};
+
static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
struct ublk_dev *dev)
{
const struct ublksrv_ctrl_dev_info *info = &dev->dev_info;
unsigned long dev_size = 250UL << 30;
+ struct fi_opts *opts = NULL;
if (ctx->auto_zc_fallback) {
ublk_err("%s: not support auto_zc_fallback\n", __func__);
@@ -35,17 +41,51 @@ static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
};
ublk_set_integrity_params(ctx, &dev->tgt.params);
- dev->private_data = (void *)(unsigned long)(ctx->fault_inject.delay_us * 1000);
+ opts = calloc(1, sizeof(*opts));
+ if (!opts) {
+ ublk_err("%s: couldn't allocate memory for opts\n", __func__);
+ return -ENOMEM;
+ }
+
+ opts->delay_ns = ctx->fault_inject.delay_us * 1000;
+ opts->die_during_fetch = ctx->fault_inject.die_during_fetch;
+ dev->private_data = opts;
+
return 0;
}
+static void ublk_fault_inject_pre_fetch_io(struct ublk_thread *t,
+ struct ublk_queue *q, int tag)
+{
+ struct fi_opts *opts = q->dev->private_data;
+
+ if (!opts->die_during_fetch)
+ return;
+
+ /*
+ * Each queue fetches its IOs in increasing order of tags, so
+ * dying just before we're about to fetch tag 1 (regardless of
+ * what queue we're on) guarantees that we've fetched a nonempty
+ * proper subset of the tags on that queue.
+ */
+ if (tag == 1) {
+ /*
+ * Ensure our commands are actually live in the kernel
+ * before we die.
+ */
+ io_uring_submit(&t->ring);
+ raise(SIGKILL);
+ }
+}
+
static int ublk_fault_inject_queue_io(struct ublk_thread *t,
struct ublk_queue *q, int tag)
{
const struct ublksrv_io_desc *iod = ublk_get_iod(q, tag);
struct io_uring_sqe *sqe;
+ struct fi_opts *opts = q->dev->private_data;
struct __kernel_timespec ts = {
- .tv_nsec = (long long)q->dev->private_data,
+ .tv_nsec = opts->delay_ns,
};
ublk_io_alloc_sqes(t, &sqe, 1);
@@ -77,29 +117,34 @@ static void ublk_fault_inject_cmd_line(struct dev_ctx *ctx, int argc, char *argv
{
static const struct option longopts[] = {
{ "delay_us", 1, NULL, 0 },
+ { "die_during_fetch", 1, NULL, 0 },
{ 0, 0, 0, 0 }
};
int option_idx, opt;
ctx->fault_inject.delay_us = 0;
+ ctx->fault_inject.die_during_fetch = false;
while ((opt = getopt_long(argc, argv, "",
longopts, &option_idx)) != -1) {
switch (opt) {
case 0:
if (!strcmp(longopts[option_idx].name, "delay_us"))
ctx->fault_inject.delay_us = strtoll(optarg, NULL, 10);
+ if (!strcmp(longopts[option_idx].name, "die_during_fetch"))
+ ctx->fault_inject.die_during_fetch = strtoll(optarg, NULL, 10);
}
}
}
static void ublk_fault_inject_usage(const struct ublk_tgt_ops *ops)
{
- printf("\tfault_inject: [--delay_us us (default 0)]\n");
+ printf("\tfault_inject: [--delay_us us (default 0)] [--die_during_fetch 1]\n");
}
const struct ublk_tgt_ops fault_inject_tgt_ops = {
.name = "fault_inject",
.init_tgt = ublk_fault_inject_tgt_init,
+ .pre_fetch_io = ublk_fault_inject_pre_fetch_io,
.queue_io = ublk_fault_inject_queue_io,
.tgt_io_done = ublk_fault_inject_tgt_io_done,
.parse_cmd_line = ublk_fault_inject_cmd_line,
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index e1c3b3c55e565c8cad6b6fe9b9b764cd244818c0..8260c96a39c05584065f41a52f3d9050614454c6 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -796,6 +796,8 @@ static void ublk_submit_fetch_commands(struct ublk_thread *t)
q = &t->dev->q[q_id];
io = &q->ios[tag];
io->buf_index = j++;
+ if (q->tgt_ops->pre_fetch_io)
+ q->tgt_ops->pre_fetch_io(t, q, tag);
ublk_queue_io_cmd(t, io);
}
} else {
@@ -807,6 +809,8 @@ static void ublk_submit_fetch_commands(struct ublk_thread *t)
for (i = 0; i < q->q_depth; i++) {
io = &q->ios[i];
io->buf_index = i;
+ if (q->tgt_ops->pre_fetch_io)
+ q->tgt_ops->pre_fetch_io(t, q, i);
ublk_queue_io_cmd(t, io);
}
}
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index 02f0c55d006b4c791fea4456687d0d8757be7be2..f784946144ad3d6e347a867fb1389a8e057766a0 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -60,6 +60,7 @@ struct stripe_ctx {
struct fault_inject_ctx {
/* fault_inject */
unsigned long delay_us;
+ bool die_during_fetch;
};
struct dev_ctx {
@@ -138,6 +139,8 @@ struct ublk_tgt_ops {
int (*init_tgt)(const struct dev_ctx *ctx, struct ublk_dev *);
void (*deinit_tgt)(struct ublk_dev *);
+ void (*pre_fetch_io)(struct ublk_thread *t, struct ublk_queue *q,
+ int tag);
int (*queue_io)(struct ublk_thread *, struct ublk_queue *, int tag);
void (*tgt_io_done)(struct ublk_thread *, struct ublk_queue *,
const struct io_uring_cqe *);
diff --git a/tools/testing/selftests/ublk/test_generic_17.sh b/tools/testing/selftests/ublk/test_generic_17.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2278b5fc9dba523bb1bf8411d22f4f95a28da905
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_generic_17.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+ERR_CODE=0
+
+_prep_test "fault_inject" "teardown after incomplete recovery"
+
+# First start and stop a ublk server with device configured for recovery
+dev_id=$(_add_ublk_dev -t fault_inject -r 1)
+_check_add_dev $TID $?
+state=$(__ublk_kill_daemon "${dev_id}" "QUIESCED")
+if [ "$state" != "QUIESCED" ]; then
+ echo "device isn't quiesced($state) after $action"
+ ERR_CODE=255
+fi
+
+# Then recover the device, but use --die_during_fetch to have the ublk
+# server die while a queue has some (but not all) I/Os fetched
+${UBLK_PROG} recover -n "${dev_id}" --foreground -t fault_inject --die_during_fetch 1
+RECOVER_RES=$?
+# 137 is the result when dying of SIGKILL
+if (( RECOVER_RES != 137 )); then
+ echo "recover command exited with unexpected code ${RECOVER_RES}!"
+ ERR_CODE=255
+fi
+
+# Clean up the device. This can only succeed once teardown of the above
+# exited ublk server completes. So if teardown never completes, we will
+# time out here
+_ublk_del_dev "${dev_id}"
+
+_cleanup_test "fault_inject"
+_show_result $TID $ERR_CODE
--
2.34.1
^ permalink raw reply related
* [PATCH 0/2] ublk: fix infinite loop in ublk server teardown
From: Uday Shankar @ 2026-04-04 3:23 UTC (permalink / raw)
To: Ming Lei, Caleb Sander Mateos, Jens Axboe, Shuah Khan
Cc: linux-block, linux-kernel, linux-kselftest, Uday Shankar
Fix an infinite loop in ublk server teardown which can arise when a ublk
server dies while recovering a device. Also add a test which
demonstrates the problem and verifies the fix.
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
---
Uday Shankar (2):
ublk: reset per-IO canceled flag on each fetch
selftests: ublk: test that teardown after incomplete recovery completes
drivers/block/ublk_drv.c | 21 ++++++----
tools/testing/selftests/ublk/Makefile | 1 +
tools/testing/selftests/ublk/fault_inject.c | 51 +++++++++++++++++++++++--
tools/testing/selftests/ublk/kublk.c | 4 ++
tools/testing/selftests/ublk/kublk.h | 3 ++
tools/testing/selftests/ublk/test_generic_17.sh | 35 +++++++++++++++++
6 files changed, 104 insertions(+), 11 deletions(-)
---
base-commit: cdd71b7feb3674d14c5edd9c133242ddf9a363f2
change-id: 20260403-cancel-bb6a1292534c
Best regards,
--
Uday Shankar <ushankar@purestorage.com>
^ permalink raw reply
* [PATCH 1/2] ublk: reset per-IO canceled flag on each fetch
From: Uday Shankar @ 2026-04-04 3:23 UTC (permalink / raw)
To: Ming Lei, Caleb Sander Mateos, Jens Axboe, Shuah Khan
Cc: linux-block, linux-kernel, linux-kselftest, Uday Shankar
In-Reply-To: <20260403-cancel-v1-0-86e5a6b3d3af@purestorage.com>
If a ublk server starts recovering devices but dies before issuing fetch
commands for all IOs, cancellation of the fetch commands that were
successfully issued may never complete. This is because the per-IO
canceled flag can remain set even after the fetch for that IO has been
submitted - the per-IO canceled flags for all IOs in a queue are reset
together only once all IOs for that queue have been fetched. So if a
nonempty proper subset of the IOs for a queue are fetched when the ublk
server dies, the IOs in that subset will never successfully be canceled,
as their canceled flags remain set, and this prevents ublk_cancel_cmd
from actually calling io_uring_cmd_done on the commands, despite the
fact that they are outstanding.
Fix this by resetting the per-IO cancel flags immediately when each IO
is fetched instead of waiting for all IOs for the queue (which may never
happen).
Signed-off-by: Uday Shankar <ushankar@purestorage.com>
---
drivers/block/ublk_drv.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 3ba7da94d31499590a06a8b307ed151919a027cb..92dabeb820344107c9fadfae94396082b933d84e 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -2916,22 +2916,26 @@ static void ublk_stop_dev(struct ublk_device *ub)
ublk_cancel_dev(ub);
}
+static void ublk_reset_io_flags(struct ublk_queue *ubq, struct ublk_io *io)
+{
+ /* UBLK_IO_FLAG_CANCELED can be cleared now */
+ spin_lock(&ubq->cancel_lock);
+ io->flags &= ~UBLK_IO_FLAG_CANCELED;
+ spin_unlock(&ubq->cancel_lock);
+}
+
/* reset per-queue io flags */
static void ublk_queue_reset_io_flags(struct ublk_queue *ubq)
{
- int j;
-
- /* UBLK_IO_FLAG_CANCELED can be cleared now */
spin_lock(&ubq->cancel_lock);
- for (j = 0; j < ubq->q_depth; j++)
- ubq->ios[j].flags &= ~UBLK_IO_FLAG_CANCELED;
ubq->canceling = false;
spin_unlock(&ubq->cancel_lock);
ubq->fail_io = false;
}
/* device can only be started after all IOs are ready */
-static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id)
+static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id,
+ struct ublk_io *io)
__must_hold(&ub->mutex)
{
struct ublk_queue *ubq = ublk_get_queue(ub, q_id);
@@ -2940,6 +2944,7 @@ static void ublk_mark_io_ready(struct ublk_device *ub, u16 q_id)
ub->unprivileged_daemons = true;
ubq->nr_io_ready++;
+ ublk_reset_io_flags(ubq, io);
/* Check if this specific queue is now fully ready */
if (ublk_queue_ready(ubq)) {
@@ -3202,7 +3207,7 @@ static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
if (!ret)
ret = ublk_config_io_buf(ub, io, cmd, buf_addr, NULL);
if (!ret)
- ublk_mark_io_ready(ub, q_id);
+ ublk_mark_io_ready(ub, q_id, io);
mutex_unlock(&ub->mutex);
return ret;
}
@@ -3610,7 +3615,7 @@ static int ublk_batch_prep_io(struct ublk_queue *ubq,
ublk_io_unlock(io);
if (!ret)
- ublk_mark_io_ready(data->ub, ubq->q_id);
+ ublk_mark_io_ready(data->ub, ubq->q_id, io);
return ret;
}
--
2.34.1
^ permalink raw reply related
* [PATCH 6/6] target: use bio_integrity_intervals() helper
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
Use bio_integrity_intervals() to convert bio->bi_iter.bi_sector to
integrity intervals to reduce code duplication. Make the same change in
the nvmet code that appears to have been copied from the target code.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
drivers/nvme/target/io-cmd-bdev.c | 3 +--
drivers/target/target_core_iblock.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index f2d9e8901df4..dcf273360015 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -218,12 +218,11 @@ static int nvmet_bdev_alloc_bip(struct nvmet_req *req, struct bio *bio,
pr_err("Unable to allocate bio_integrity_payload\n");
return PTR_ERR(bip);
}
/* virtual start sector must be in integrity interval units */
- bip_set_seed(bip, bio->bi_iter.bi_sector >>
- (bi->interval_exp - SECTOR_SHIFT));
+ bip_set_seed(bip, bio_integrity_intervals(bi, bio->bi_iter.bi_sector));
resid = bio_integrity_bytes(bi, bio_sectors(bio));
while (resid > 0 && sg_miter_next(miter)) {
len = min_t(size_t, miter->length, resid);
rc = bio_integrity_add_page(bio, miter->page, len,
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 1087d1d17c36..434ef2b0b120 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -706,12 +706,11 @@ iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio,
pr_err("Unable to allocate bio_integrity_payload\n");
return PTR_ERR(bip);
}
/* virtual start sector must be in integrity interval units */
- bip_set_seed(bip, bio->bi_iter.bi_sector >>
- (bi->interval_exp - SECTOR_SHIFT));
+ bip_set_seed(bip, bio_integrity_intervals(bi, bio->bi_iter.bi_sector));
pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size,
(unsigned long long)bip->bip_iter.bi_sector);
resid = bio_integrity_bytes(bi, bio_sectors(bio));
--
2.45.2
^ permalink raw reply related
* [PATCH 3/6] bio-integrity-fs: pass data iter to bio_integrity_verify()
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
bio_integrity_verify() expects the passed struct bvec_iter to be an
iterator over bio data, not integrity. So construct a separate data
bvec_iter without the bio_integrity_bytes() conversion and pass it to
bio_integrity_verify() instead of bip_iter.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Fixes: 0bde8a12b554 ("block: add fs_bio_integrity helpers")
---
block/bio-integrity-fs.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/block/bio-integrity-fs.c b/block/bio-integrity-fs.c
index acb1e5f270d2..389372803b38 100644
--- a/block/bio-integrity-fs.c
+++ b/block/bio-integrity-fs.c
@@ -53,21 +53,22 @@ EXPORT_SYMBOL_GPL(fs_bio_integrity_generate);
int fs_bio_integrity_verify(struct bio *bio, sector_t sector, unsigned int size)
{
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
+ struct bvec_iter data_iter = {.bi_sector = sector, .bi_size = size};
/*
* Reinitialize bip->bip_iter.
*
* This is for use in the submitter after the driver is done with the
* bio. Requires the submitter to remember the sector and the size.
*/
memset(&bip->bip_iter, 0, sizeof(bip->bip_iter));
bip->bip_iter.bi_sector = sector;
bip->bip_iter.bi_size = bio_integrity_bytes(bi, size >> SECTOR_SHIFT);
- return blk_status_to_errno(bio_integrity_verify(bio, &bip->bip_iter));
+ return blk_status_to_errno(bio_integrity_verify(bio, &data_iter));
}
static int __init fs_bio_integrity_init(void)
{
fs_bio_integrity_cache = kmem_cache_create("fs_bio_integrity",
--
2.45.2
^ permalink raw reply related
* [PATCH 4/6] bio-integrity-fs: use integrity interval instead of sector as seed
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
bip_iter.bi_sector is meant to be in units of integrity intervals rather
than 512-byte sectors. bio_integrity_verify() doesn't actually use it
currently (it uses the passed in struct bvec_iter's bi_sector instead).
But let's set it to the expected value for consistency.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
block/bio-integrity-fs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/bio-integrity-fs.c b/block/bio-integrity-fs.c
index 389372803b38..5d1b0e33fc5f 100644
--- a/block/bio-integrity-fs.c
+++ b/block/bio-integrity-fs.c
@@ -62,11 +62,11 @@ int fs_bio_integrity_verify(struct bio *bio, sector_t sector, unsigned int size)
*
* This is for use in the submitter after the driver is done with the
* bio. Requires the submitter to remember the sector and the size.
*/
memset(&bip->bip_iter, 0, sizeof(bip->bip_iter));
- bip->bip_iter.bi_sector = sector;
+ bip->bip_iter.bi_sector = bio_integrity_intervals(bi, sector);
bip->bip_iter.bi_size = bio_integrity_bytes(bi, size >> SECTOR_SHIFT);
return blk_status_to_errno(bio_integrity_verify(bio, &data_iter));
}
static int __init fs_bio_integrity_init(void)
--
2.45.2
^ permalink raw reply related
* [PATCH 1/6] blk-integrity: take sector_t in bio_integrity_intervals()
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
To allow bio_integrity_intervals() to convert an absolute sector_t to an
absolute integrity interval, change its argument type to sector_t and
its return type to u64.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
include/linux/blk-integrity.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h
index b1b530613c34..2e366f03a3d8 100644
--- a/include/linux/blk-integrity.h
+++ b/include/linux/blk-integrity.h
@@ -64,21 +64,21 @@ queue_max_integrity_segments(const struct request_queue *q)
{
return q->limits.max_integrity_segments;
}
/**
- * bio_integrity_intervals - Return number of integrity intervals for a bio
+ * bio_integrity_intervals - Convert sectors to integrity intervals
* @bi: blk_integrity profile for device
- * @sectors: Size of the bio in 512-byte sectors
+ * @sectors: Number of 512-byte sectors
*
* Description: The block layer calculates everything in 512 byte
* sectors but integrity metadata is done in terms of the data integrity
* interval size of the storage device. Convert the block layer sectors
* to the appropriate number of integrity intervals.
*/
-static inline unsigned int bio_integrity_intervals(struct blk_integrity *bi,
- unsigned int sectors)
+static inline u64 bio_integrity_intervals(struct blk_integrity *bi,
+ sector_t sectors)
{
return sectors >> (bi->interval_exp - 9);
}
static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
@@ -151,12 +151,12 @@ static inline unsigned short
queue_max_integrity_segments(const struct request_queue *q)
{
return 0;
}
-static inline unsigned int bio_integrity_intervals(struct blk_integrity *bi,
- unsigned int sectors)
+static inline u64 bio_integrity_intervals(struct blk_integrity *bi,
+ sector_t sectors)
{
return 0;
}
static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
--
2.45.2
^ permalink raw reply related
* [PATCH 5/6] t10-pi: use bio_integrity_intervals() helper
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
Use bio_integrity_intervals() to convert blk_rq_pos(rq) to integrity
intervals to reduce code duplication.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
block/t10-pi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/t10-pi.c b/block/t10-pi.c
index 36475369cd16..112015cdeb72 100644
--- a/block/t10-pi.c
+++ b/block/t10-pi.c
@@ -540,11 +540,11 @@ static void __blk_reftag_remap(struct bio *bio, struct blk_integrity *bi,
static void blk_integrity_remap(struct request *rq, unsigned int nr_bytes,
bool prep)
{
struct blk_integrity *bi = &rq->q->limits.integrity;
- u64 ref = blk_rq_pos(rq) >> (bi->interval_exp - SECTOR_SHIFT);
+ u64 ref = bio_integrity_intervals(bi, blk_rq_pos(rq));
unsigned intervals = nr_bytes >> bi->interval_exp;
struct bio *bio;
if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
return;
--
2.45.2
^ permalink raw reply related
* [PATCH 2/6] block: use integrity interval instead of sector as seed
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
In-Reply-To: <20260403194109.2255933-1-csander@purestorage.com>
bio_integrity_setup_default() and blk_integrity_iterate() set the
integrity seed (initial reference tag) to the absolute address in the
block device in units of 512-byte sectors. The seed is correctly
incremented/decremented in units of integrity intervals in
bio_integrity_map_iter(), bio_integrity_advance(), and
blk_integrity_interval(). As a result, the ref tag written or read to a
particular integrity interval on a block device with integrity interval
size > 512 bytes varies with the starting offset of the read/write.
Convert the initial seed to units of integrity intervals so a consistent
ref tag is used for each integrity interval.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Fixes: 3be91c4a3d09 ("block: Deprecate the use of the term sector in the context of block integrity")
Fixes: 63573e359d05 ("bio-integrity: Restore original iterator on verify stage")
---
block/bio-integrity.c | 2 +-
block/t10-pi.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index e79eaf047794..4be2cf649e54 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -104,11 +104,11 @@ void bio_integrity_free_buf(struct bio_integrity_payload *bip)
void bio_integrity_setup_default(struct bio *bio)
{
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
- bip_set_seed(bip, bio->bi_iter.bi_sector);
+ bip_set_seed(bip, bio_integrity_intervals(bi, bio->bi_iter.bi_sector));
if (bi->csum_type) {
bip->bip_flags |= BIP_CHECK_GUARD;
if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
bip->bip_flags |= BIP_IP_CHECKSUM;
diff --git a/block/t10-pi.c b/block/t10-pi.c
index a19b4e102a83..36475369cd16 100644
--- a/block/t10-pi.c
+++ b/block/t10-pi.c
@@ -315,11 +315,11 @@ static blk_status_t blk_integrity_iterate(struct bio *bio,
.bip = bip,
.bi = bi,
.data_iter = *data_iter,
.prot_iter = bip->bip_iter,
.interval_remaining = 1 << bi->interval_exp,
- .seed = data_iter->bi_sector,
+ .seed = bio_integrity_intervals(bi, data_iter->bi_sector),
.csum = 0,
};
blk_status_t ret = BLK_STS_OK;
while (iter.data_iter.bi_size && ret == BLK_STS_OK) {
--
2.45.2
^ permalink raw reply related
* [PATCH 0/6] block: fix integrity offset/length conversions
From: Caleb Sander Mateos @ 2026-04-03 19:41 UTC (permalink / raw)
To: Jens Axboe, Christoph Hellwig, Sagi Grimberg, Chaitanya Kulkarni,
Martin K. Petersen
Cc: linux-block, linux-kernel, linux-nvme, linux-scsi, target-devel,
Caleb Sander Mateos
The block layer's integrity code currently sets the seed (initial
reference tag) in units of 512-byte sectors but increments it in units
of integrity intervals. Not only do the T10 DIF formats require ref tags
to be the lower bits of the logical block address, but mixing the two
units means the ref tags used for a particular logical block vary based
on its offset within a read/write request. This looks to be a
longstanding bug affecting block devices that support integrity with
block sizes > 512 bytes; I'm surprised it wasn't noticed before.
Also fix the newly added fs_bio_integrity_verify() to pass
bio_integrity_verify() a struct bdev_iter representing the data instead
of the integrity. Most of the integrity data is currently being skipped.
Caleb Sander Mateos (6):
blk-integrity: take sector_t in bio_integrity_intervals()
block: use integrity interval instead of sector as seed
bio-integrity-fs: pass data iter to bio_integrity_verify()
bio-integrity-fs: use integrity interval instead of sector as seed
t10-pi: use bio_integrity_intervals() helper
target: use bio_integrity_intervals() helper
block/bio-integrity-fs.c | 5 +++--
block/bio-integrity.c | 2 +-
block/t10-pi.c | 4 ++--
drivers/nvme/target/io-cmd-bdev.c | 3 +--
drivers/target/target_core_iblock.c | 3 +--
include/linux/blk-integrity.h | 12 ++++++------
6 files changed, 14 insertions(+), 15 deletions(-)
--
2.45.2
^ permalink raw reply
* [PATCH] t10-pi: reduce ref tag code duplication
From: Caleb Sander Mateos @ 2026-04-03 18:51 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, Caleb Sander Mateos, linux-kernel
t10_pi_ref_tag() and ext_pi_ref_tag() are identical except for the final
truncation of the ref tag to 32 or 48 bits. Factor out a helper
full_pi_ref_tag() to return the untruncated ref tag and use it in
t10_pi_ref_tag() and ext_pi_ref_tag().
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
include/linux/t10-pi.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h
index 2c59fe3efcd4..c6fe5db47c7a 100644
--- a/include/linux/t10-pi.h
+++ b/include/linux/t10-pi.h
@@ -35,18 +35,23 @@ struct t10_pi_tuple {
};
#define T10_PI_APP_ESCAPE cpu_to_be16(0xffff)
#define T10_PI_REF_ESCAPE cpu_to_be32(0xffffffff)
-static inline u32 t10_pi_ref_tag(struct request *rq)
+static inline u64 full_pi_ref_tag(struct request *rq)
{
unsigned int shift = ilog2(queue_logical_block_size(rq->q));
if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
rq->q->limits.integrity.interval_exp)
shift = rq->q->limits.integrity.interval_exp;
- return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT) & 0xffffffff;
+ return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT);
+}
+
+static inline u32 t10_pi_ref_tag(struct request *rq)
+{
+ return full_pi_ref_tag(rq) & 0xffffffff;
}
struct crc64_pi_tuple {
__be64 guard_tag;
__be16 app_tag;
@@ -62,14 +67,9 @@ static inline u64 lower_48_bits(u64 n)
return n & ((1ull << 48) - 1);
}
static inline u64 ext_pi_ref_tag(struct request *rq)
{
- unsigned int shift = ilog2(queue_logical_block_size(rq->q));
-
- if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) &&
- rq->q->limits.integrity.interval_exp)
- shift = rq->q->limits.integrity.interval_exp;
- return lower_48_bits(blk_rq_pos(rq) >> (shift - SECTOR_SHIFT));
+ return lower_48_bits(full_pi_ref_tag(rq));
}
#endif
--
2.45.2
^ permalink raw reply related
* [PATCH] bdev: remove unused BVEC_ITER_ALL_INIT
From: Caleb Sander Mateos @ 2026-04-03 18:48 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, Caleb Sander Mateos, linux-kernel
This macro no longer has any users, so remove it.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
include/linux/bvec.h | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index 06fb60471aaf..d36dd476feda 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -201,19 +201,10 @@ static inline void bvec_iter_advance_single(const struct bio_vec *bv,
for (iter = (start); \
(iter).bi_size && \
((bvl = mp_bvec_iter_bvec((bio_vec), (iter))), 1); \
bvec_iter_advance_single((bio_vec), &(iter), (bvl).bv_len))
-/* for iterating one bio from start to end */
-#define BVEC_ITER_ALL_INIT (struct bvec_iter) \
-{ \
- .bi_sector = 0, \
- .bi_size = UINT_MAX, \
- .bi_idx = 0, \
- .bi_bvec_done = 0, \
-}
-
static inline struct bio_vec *bvec_init_iter_all(struct bvec_iter_all *iter_all)
{
iter_all->done = 0;
iter_all->idx = 0;
--
2.45.2
^ permalink raw reply related
* [PATCH] drbd: remove DRBD_GENLA_F_MANDATORY flag handling
From: Christoph Böhmwalder @ 2026-04-03 13:29 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-kernel, Lars Ellenberg, Philipp Reisner,
linux-block, Christoph Böhmwalder, Johannes Berg,
Jakub Kicinski
DRBD used a custom mechanism to mark netlink attributes as "mandatory":
bit 14 of nla_type was repurposed as DRBD_GENLA_F_MANDATORY. Attributes
sent from userspace that had this bit present and that were unknown
to the kernel would lead to an error.
Since commit ef6243acb478 ("genetlink: optionally validate strictly/dumps"),
the generic netlink layer rejects unknown top-level attributes when
strict validation is enabled. DRBD never opted out of strict
validation, so unknown top-level attributes are already rejected by
the netlink core.
The mandatory flag mechanism was required for nested attributes, because
these are parsed liberally, silently dropping attributes unknown to the
kernel.
This prepares for the move to a new YNL-based family, which will use the
now-default strict parsing.
The current family is not expected to gain any new attributes, which
makes this change safe.
Old userspace that still sets bit 14 is unaffected: nla_type()
strips it before __nla_validate_parse() performs attribute validation,
so the bit never reaches DRBD.
Remove all references to the mandatory flag in DRBD.
Cc: Johannes Berg <johannes.berg@intel.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/Makefile | 1 -
drivers/block/drbd/drbd_nl.c | 19 +--
drivers/block/drbd/drbd_nla.c | 56 --------
drivers/block/drbd/drbd_nla.h | 9 --
include/linux/drbd_genl.h | 208 +++++++++++++++---------------
include/linux/genl_magic_func.h | 3 +-
include/linux/genl_magic_struct.h | 15 +--
7 files changed, 114 insertions(+), 197 deletions(-)
delete mode 100644 drivers/block/drbd/drbd_nla.c
delete mode 100644 drivers/block/drbd/drbd_nla.h
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
index 67a8b352a1d5..187eaf81f0f8 100644
--- a/drivers/block/drbd/Makefile
+++ b/drivers/block/drbd/Makefile
@@ -3,7 +3,6 @@ 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_nla.o
drbd-$(CONFIG_DEBUG_FS) += drbd_debugfs.o
obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 1f8ffdf9b24e..d997d274092c 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -74,7 +74,6 @@ 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>
-#include "drbd_nla.h"
static int drbd_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
@@ -239,14 +238,14 @@ static int drbd_adm_prepare(struct drbd_config_context *adm_ctx,
goto fail;
/* and assign stuff to the adm_ctx */
- nla = nested_attr_tb[__nla_type(T_ctx_volume)];
+ nla = nested_attr_tb[T_ctx_volume];
if (nla)
adm_ctx->volume = nla_get_u32(nla);
- nla = nested_attr_tb[__nla_type(T_ctx_resource_name)];
+ nla = nested_attr_tb[T_ctx_resource_name];
if (nla)
adm_ctx->resource_name = nla_data(nla);
- adm_ctx->my_addr = nested_attr_tb[__nla_type(T_ctx_my_addr)];
- adm_ctx->peer_addr = nested_attr_tb[__nla_type(T_ctx_peer_addr)];
+ adm_ctx->my_addr = nested_attr_tb[T_ctx_my_addr];
+ adm_ctx->peer_addr = nested_attr_tb[T_ctx_peer_addr];
if ((adm_ctx->my_addr &&
nla_len(adm_ctx->my_addr) > sizeof(adm_ctx->connection->my_addr)) ||
(adm_ctx->peer_addr &&
@@ -825,7 +824,6 @@ drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int for
static const char *from_attrs_err_to_txt(int err)
{
return err == -ENOMSG ? "required attribute missing" :
- err == -EOPNOTSUPP ? "unknown mandatory attribute" :
err == -EEXIST ? "can not change invariant setting" :
"invalid attribute value";
}
@@ -3303,14 +3301,13 @@ static int nla_put_drbd_cfg_context(struct sk_buff *skb,
static struct nlattr *find_cfg_context_attr(const struct nlmsghdr *nlh, int attr)
{
const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ;
- const int maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1;
struct nlattr *nla;
nla = nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen),
DRBD_NLA_CFG_CONTEXT);
if (!nla)
return NULL;
- return drbd_nla_find_nested(maxtype, nla, __nla_type(attr));
+ return nla_find_nested(nla, attr);
}
static void resource_to_info(struct resource_info *, struct drbd_resource *);
@@ -4068,7 +4065,6 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
struct nlattr *nla;
const char *resource_name;
struct drbd_resource *resource;
- int maxtype;
/* Is this a followup call? */
if (cb->args[0]) {
@@ -4088,10 +4084,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
/* No explicit context given. Dump all. */
if (!nla)
goto dump;
- maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1;
- nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name));
- if (IS_ERR(nla))
- return PTR_ERR(nla);
+ nla = nla_find_nested(nla, T_ctx_resource_name);
/* context given, but no name present? */
if (!nla)
return -EINVAL;
diff --git a/drivers/block/drbd/drbd_nla.c b/drivers/block/drbd/drbd_nla.c
deleted file mode 100644
index df0d241d3f6a..000000000000
--- a/drivers/block/drbd/drbd_nla.c
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-#include <linux/kernel.h>
-#include <net/netlink.h>
-#include <linux/drbd_genl_api.h>
-#include "drbd_nla.h"
-
-static int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla)
-{
- struct nlattr *head = nla_data(nla);
- int len = nla_len(nla);
- int rem;
-
- /*
- * validate_nla (called from nla_parse_nested) ignores attributes
- * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag.
- * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY
- * flag set also, check and remove that flag before calling
- * nla_parse_nested.
- */
-
- nla_for_each_attr(nla, head, len, rem) {
- if (nla->nla_type & DRBD_GENLA_F_MANDATORY) {
- nla->nla_type &= ~DRBD_GENLA_F_MANDATORY;
- if (nla_type(nla) > maxtype)
- return -EOPNOTSUPP;
- }
- }
- return 0;
-}
-
-int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
- const struct nla_policy *policy)
-{
- int err;
-
- err = drbd_nla_check_mandatory(maxtype, nla);
- if (!err)
- err = nla_parse_nested_deprecated(tb, maxtype, nla, policy,
- NULL);
-
- return err;
-}
-
-struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype)
-{
- int err;
- /*
- * If any nested attribute has the DRBD_GENLA_F_MANDATORY flag set and
- * we don't know about that attribute, reject all the nested
- * attributes.
- */
- err = drbd_nla_check_mandatory(maxtype, nla);
- if (err)
- return ERR_PTR(err);
- return nla_find_nested(nla, attrtype);
-}
diff --git a/drivers/block/drbd/drbd_nla.h b/drivers/block/drbd/drbd_nla.h
deleted file mode 100644
index d3555df0d353..000000000000
--- a/drivers/block/drbd/drbd_nla.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef __DRBD_NLA_H
-#define __DRBD_NLA_H
-
-extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,
- const struct nla_policy *policy);
-extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype);
-
-#endif /* __DRBD_NLA_H */
diff --git a/include/linux/drbd_genl.h b/include/linux/drbd_genl.h
index 53f44b8cd75f..f53c534aba0c 100644
--- a/include/linux/drbd_genl.h
+++ b/include/linux/drbd_genl.h
@@ -87,7 +87,7 @@
*/
GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply,
/* "arbitrary" size strings, nla_policy.len = 0 */
- __str_field(1, DRBD_GENLA_F_MANDATORY, info_text, 0)
+ __str_field(1, 0, info_text, 0)
)
/* Configuration requests typically need a context to operate on.
@@ -96,10 +96,10 @@ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply,
* and/or the replication group (aka resource) name,
* and the volume id within the resource. */
GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context,
- __u32_field(1, DRBD_GENLA_F_MANDATORY, ctx_volume)
- __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_resource_name, 128)
- __bin_field(3, DRBD_GENLA_F_MANDATORY, ctx_my_addr, 128)
- __bin_field(4, DRBD_GENLA_F_MANDATORY, ctx_peer_addr, 128)
+ __u32_field(1, 0, ctx_volume)
+ __str_field(2, 0, ctx_resource_name, 128)
+ __bin_field(3, 0, ctx_my_addr, 128)
+ __bin_field(4, 0, ctx_peer_addr, 128)
)
GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf,
@@ -108,86 +108,86 @@ GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf,
__s32_field(3, DRBD_F_REQUIRED | DRBD_F_INVARIANT, meta_dev_idx)
/* use the resize command to try and change the disk_size */
- __u64_field(4, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, disk_size)
+ __u64_field(4, DRBD_F_INVARIANT, disk_size)
/* we could change the max_bio_bvecs,
* but it won't propagate through the stack */
- __u32_field(5, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, max_bio_bvecs)
-
- __u32_field_def(6, DRBD_GENLA_F_MANDATORY, on_io_error, DRBD_ON_IO_ERROR_DEF)
- __u32_field_def(7, DRBD_GENLA_F_MANDATORY, fencing, DRBD_FENCING_DEF)
-
- __u32_field_def(8, DRBD_GENLA_F_MANDATORY, resync_rate, DRBD_RESYNC_RATE_DEF)
- __s32_field_def(9, DRBD_GENLA_F_MANDATORY, resync_after, DRBD_MINOR_NUMBER_DEF)
- __u32_field_def(10, DRBD_GENLA_F_MANDATORY, al_extents, DRBD_AL_EXTENTS_DEF)
- __u32_field_def(11, DRBD_GENLA_F_MANDATORY, c_plan_ahead, DRBD_C_PLAN_AHEAD_DEF)
- __u32_field_def(12, DRBD_GENLA_F_MANDATORY, c_delay_target, DRBD_C_DELAY_TARGET_DEF)
- __u32_field_def(13, DRBD_GENLA_F_MANDATORY, c_fill_target, DRBD_C_FILL_TARGET_DEF)
- __u32_field_def(14, DRBD_GENLA_F_MANDATORY, c_max_rate, DRBD_C_MAX_RATE_DEF)
- __u32_field_def(15, DRBD_GENLA_F_MANDATORY, c_min_rate, DRBD_C_MIN_RATE_DEF)
- __u32_field_def(20, DRBD_GENLA_F_MANDATORY, disk_timeout, DRBD_DISK_TIMEOUT_DEF)
+ __u32_field(5, DRBD_F_INVARIANT, max_bio_bvecs)
+
+ __u32_field_def(6, 0, on_io_error, DRBD_ON_IO_ERROR_DEF)
+ __u32_field_def(7, 0, fencing, DRBD_FENCING_DEF)
+
+ __u32_field_def(8, 0, resync_rate, DRBD_RESYNC_RATE_DEF)
+ __s32_field_def(9, 0, resync_after, DRBD_MINOR_NUMBER_DEF)
+ __u32_field_def(10, 0, al_extents, DRBD_AL_EXTENTS_DEF)
+ __u32_field_def(11, 0, c_plan_ahead, DRBD_C_PLAN_AHEAD_DEF)
+ __u32_field_def(12, 0, c_delay_target, DRBD_C_DELAY_TARGET_DEF)
+ __u32_field_def(13, 0, c_fill_target, DRBD_C_FILL_TARGET_DEF)
+ __u32_field_def(14, 0, c_max_rate, DRBD_C_MAX_RATE_DEF)
+ __u32_field_def(15, 0, c_min_rate, DRBD_C_MIN_RATE_DEF)
+ __u32_field_def(20, 0, disk_timeout, DRBD_DISK_TIMEOUT_DEF)
__u32_field_def(21, 0 /* OPTIONAL */, read_balancing, DRBD_READ_BALANCING_DEF)
__u32_field_def(25, 0 /* OPTIONAL */, rs_discard_granularity, DRBD_RS_DISCARD_GRANULARITY_DEF)
- __flg_field_def(16, DRBD_GENLA_F_MANDATORY, disk_barrier, DRBD_DISK_BARRIER_DEF)
- __flg_field_def(17, DRBD_GENLA_F_MANDATORY, disk_flushes, DRBD_DISK_FLUSHES_DEF)
- __flg_field_def(18, DRBD_GENLA_F_MANDATORY, disk_drain, DRBD_DISK_DRAIN_DEF)
- __flg_field_def(19, DRBD_GENLA_F_MANDATORY, md_flushes, DRBD_MD_FLUSHES_DEF)
+ __flg_field_def(16, 0, disk_barrier, DRBD_DISK_BARRIER_DEF)
+ __flg_field_def(17, 0, disk_flushes, DRBD_DISK_FLUSHES_DEF)
+ __flg_field_def(18, 0, disk_drain, DRBD_DISK_DRAIN_DEF)
+ __flg_field_def(19, 0, md_flushes, DRBD_MD_FLUSHES_DEF)
__flg_field_def(23, 0 /* OPTIONAL */, al_updates, DRBD_AL_UPDATES_DEF)
__flg_field_def(24, 0 /* OPTIONAL */, discard_zeroes_if_aligned, DRBD_DISCARD_ZEROES_IF_ALIGNED_DEF)
__flg_field_def(26, 0 /* OPTIONAL */, disable_write_same, DRBD_DISABLE_WRITE_SAME_DEF)
)
GENL_struct(DRBD_NLA_RESOURCE_OPTS, 4, res_opts,
- __str_field_def(1, DRBD_GENLA_F_MANDATORY, cpu_mask, DRBD_CPU_MASK_SIZE)
- __u32_field_def(2, DRBD_GENLA_F_MANDATORY, on_no_data, DRBD_ON_NO_DATA_DEF)
+ __str_field_def(1, 0, cpu_mask, DRBD_CPU_MASK_SIZE)
+ __u32_field_def(2, 0, on_no_data, DRBD_ON_NO_DATA_DEF)
)
GENL_struct(DRBD_NLA_NET_CONF, 5, net_conf,
- __str_field_def(1, DRBD_GENLA_F_MANDATORY | DRBD_F_SENSITIVE,
+ __str_field_def(1, DRBD_F_SENSITIVE,
shared_secret, SHARED_SECRET_MAX)
- __str_field_def(2, DRBD_GENLA_F_MANDATORY, cram_hmac_alg, SHARED_SECRET_MAX)
- __str_field_def(3, DRBD_GENLA_F_MANDATORY, integrity_alg, SHARED_SECRET_MAX)
- __str_field_def(4, DRBD_GENLA_F_MANDATORY, verify_alg, SHARED_SECRET_MAX)
- __str_field_def(5, DRBD_GENLA_F_MANDATORY, csums_alg, SHARED_SECRET_MAX)
- __u32_field_def(6, DRBD_GENLA_F_MANDATORY, wire_protocol, DRBD_PROTOCOL_DEF)
- __u32_field_def(7, DRBD_GENLA_F_MANDATORY, connect_int, DRBD_CONNECT_INT_DEF)
- __u32_field_def(8, DRBD_GENLA_F_MANDATORY, timeout, DRBD_TIMEOUT_DEF)
- __u32_field_def(9, DRBD_GENLA_F_MANDATORY, ping_int, DRBD_PING_INT_DEF)
- __u32_field_def(10, DRBD_GENLA_F_MANDATORY, ping_timeo, DRBD_PING_TIMEO_DEF)
- __u32_field_def(11, DRBD_GENLA_F_MANDATORY, sndbuf_size, DRBD_SNDBUF_SIZE_DEF)
- __u32_field_def(12, DRBD_GENLA_F_MANDATORY, rcvbuf_size, DRBD_RCVBUF_SIZE_DEF)
- __u32_field_def(13, DRBD_GENLA_F_MANDATORY, ko_count, DRBD_KO_COUNT_DEF)
- __u32_field_def(14, DRBD_GENLA_F_MANDATORY, max_buffers, DRBD_MAX_BUFFERS_DEF)
- __u32_field_def(15, DRBD_GENLA_F_MANDATORY, max_epoch_size, DRBD_MAX_EPOCH_SIZE_DEF)
- __u32_field_def(16, DRBD_GENLA_F_MANDATORY, unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF)
- __u32_field_def(17, DRBD_GENLA_F_MANDATORY, after_sb_0p, DRBD_AFTER_SB_0P_DEF)
- __u32_field_def(18, DRBD_GENLA_F_MANDATORY, after_sb_1p, DRBD_AFTER_SB_1P_DEF)
- __u32_field_def(19, DRBD_GENLA_F_MANDATORY, after_sb_2p, DRBD_AFTER_SB_2P_DEF)
- __u32_field_def(20, DRBD_GENLA_F_MANDATORY, rr_conflict, DRBD_RR_CONFLICT_DEF)
- __u32_field_def(21, DRBD_GENLA_F_MANDATORY, on_congestion, DRBD_ON_CONGESTION_DEF)
- __u32_field_def(22, DRBD_GENLA_F_MANDATORY, cong_fill, DRBD_CONG_FILL_DEF)
- __u32_field_def(23, DRBD_GENLA_F_MANDATORY, cong_extents, DRBD_CONG_EXTENTS_DEF)
- __flg_field_def(24, DRBD_GENLA_F_MANDATORY, two_primaries, DRBD_ALLOW_TWO_PRIMARIES_DEF)
- __flg_field(25, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, discard_my_data)
- __flg_field_def(26, DRBD_GENLA_F_MANDATORY, tcp_cork, DRBD_TCP_CORK_DEF)
- __flg_field_def(27, DRBD_GENLA_F_MANDATORY, always_asbp, DRBD_ALWAYS_ASBP_DEF)
- __flg_field(28, DRBD_GENLA_F_MANDATORY | DRBD_F_INVARIANT, tentative)
- __flg_field_def(29, DRBD_GENLA_F_MANDATORY, use_rle, DRBD_USE_RLE_DEF)
- /* 9: __u32_field_def(30, DRBD_GENLA_F_MANDATORY, fencing_policy, DRBD_FENCING_DEF) */
- /* 9: __str_field_def(31, DRBD_GENLA_F_MANDATORY, name, SHARED_SECRET_MAX) */
+ __str_field_def(2, 0, cram_hmac_alg, SHARED_SECRET_MAX)
+ __str_field_def(3, 0, integrity_alg, SHARED_SECRET_MAX)
+ __str_field_def(4, 0, verify_alg, SHARED_SECRET_MAX)
+ __str_field_def(5, 0, csums_alg, SHARED_SECRET_MAX)
+ __u32_field_def(6, 0, wire_protocol, DRBD_PROTOCOL_DEF)
+ __u32_field_def(7, 0, connect_int, DRBD_CONNECT_INT_DEF)
+ __u32_field_def(8, 0, timeout, DRBD_TIMEOUT_DEF)
+ __u32_field_def(9, 0, ping_int, DRBD_PING_INT_DEF)
+ __u32_field_def(10, 0, ping_timeo, DRBD_PING_TIMEO_DEF)
+ __u32_field_def(11, 0, sndbuf_size, DRBD_SNDBUF_SIZE_DEF)
+ __u32_field_def(12, 0, rcvbuf_size, DRBD_RCVBUF_SIZE_DEF)
+ __u32_field_def(13, 0, ko_count, DRBD_KO_COUNT_DEF)
+ __u32_field_def(14, 0, max_buffers, DRBD_MAX_BUFFERS_DEF)
+ __u32_field_def(15, 0, max_epoch_size, DRBD_MAX_EPOCH_SIZE_DEF)
+ __u32_field_def(16, 0, unplug_watermark, DRBD_UNPLUG_WATERMARK_DEF)
+ __u32_field_def(17, 0, after_sb_0p, DRBD_AFTER_SB_0P_DEF)
+ __u32_field_def(18, 0, after_sb_1p, DRBD_AFTER_SB_1P_DEF)
+ __u32_field_def(19, 0, after_sb_2p, DRBD_AFTER_SB_2P_DEF)
+ __u32_field_def(20, 0, rr_conflict, DRBD_RR_CONFLICT_DEF)
+ __u32_field_def(21, 0, on_congestion, DRBD_ON_CONGESTION_DEF)
+ __u32_field_def(22, 0, cong_fill, DRBD_CONG_FILL_DEF)
+ __u32_field_def(23, 0, cong_extents, DRBD_CONG_EXTENTS_DEF)
+ __flg_field_def(24, 0, two_primaries, DRBD_ALLOW_TWO_PRIMARIES_DEF)
+ __flg_field(25, DRBD_F_INVARIANT, discard_my_data)
+ __flg_field_def(26, 0, tcp_cork, DRBD_TCP_CORK_DEF)
+ __flg_field_def(27, 0, always_asbp, DRBD_ALWAYS_ASBP_DEF)
+ __flg_field(28, DRBD_F_INVARIANT, tentative)
+ __flg_field_def(29, 0, use_rle, DRBD_USE_RLE_DEF)
+ /* 9: __u32_field_def(30, 0, fencing_policy, DRBD_FENCING_DEF) */
+ /* 9: __str_field_def(31, 0, name, SHARED_SECRET_MAX) */
/* 9: __u32_field(32, DRBD_F_REQUIRED | DRBD_F_INVARIANT, peer_node_id) */
__flg_field_def(33, 0 /* OPTIONAL */, csums_after_crash_only, DRBD_CSUMS_AFTER_CRASH_ONLY_DEF)
__u32_field_def(34, 0 /* OPTIONAL */, sock_check_timeo, DRBD_SOCKET_CHECK_TIMEO_DEF)
)
GENL_struct(DRBD_NLA_SET_ROLE_PARMS, 6, set_role_parms,
- __flg_field(1, DRBD_GENLA_F_MANDATORY, assume_uptodate)
+ __flg_field(1, 0, assume_uptodate)
)
GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms,
- __u64_field(1, DRBD_GENLA_F_MANDATORY, resize_size)
- __flg_field(2, DRBD_GENLA_F_MANDATORY, resize_force)
- __flg_field(3, DRBD_GENLA_F_MANDATORY, no_resync)
+ __u64_field(1, 0, resize_size)
+ __flg_field(2, 0, resize_force)
+ __flg_field(3, 0, no_resync)
__u32_field_def(4, 0 /* OPTIONAL */, al_stripes, DRBD_AL_STRIPES_DEF)
__u32_field_def(5, 0 /* OPTIONAL */, al_stripe_size, DRBD_AL_STRIPE_SIZE_DEF)
)
@@ -195,31 +195,31 @@ GENL_struct(DRBD_NLA_RESIZE_PARMS, 7, resize_parms,
GENL_struct(DRBD_NLA_STATE_INFO, 8, state_info,
/* the reason of the broadcast,
* if this is an event triggered broadcast. */
- __u32_field(1, DRBD_GENLA_F_MANDATORY, sib_reason)
+ __u32_field(1, 0, sib_reason)
__u32_field(2, DRBD_F_REQUIRED, current_state)
- __u64_field(3, DRBD_GENLA_F_MANDATORY, capacity)
- __u64_field(4, DRBD_GENLA_F_MANDATORY, ed_uuid)
+ __u64_field(3, 0, capacity)
+ __u64_field(4, 0, ed_uuid)
/* These are for broadcast from after state change work.
* prev_state and new_state are from the moment the state change took
* place, new_state is not neccessarily the same as current_state,
* there may have been more state changes since. Which will be
* broadcasted soon, in their respective after state change work. */
- __u32_field(5, DRBD_GENLA_F_MANDATORY, prev_state)
- __u32_field(6, DRBD_GENLA_F_MANDATORY, new_state)
+ __u32_field(5, 0, prev_state)
+ __u32_field(6, 0, new_state)
/* if we have a local disk: */
- __bin_field(7, DRBD_GENLA_F_MANDATORY, uuids, (UI_SIZE*sizeof(__u64)))
- __u32_field(8, DRBD_GENLA_F_MANDATORY, disk_flags)
- __u64_field(9, DRBD_GENLA_F_MANDATORY, bits_total)
- __u64_field(10, DRBD_GENLA_F_MANDATORY, bits_oos)
+ __bin_field(7, 0, uuids, (UI_SIZE*sizeof(__u64)))
+ __u32_field(8, 0, disk_flags)
+ __u64_field(9, 0, bits_total)
+ __u64_field(10, 0, bits_oos)
/* and in case resync or online verify is active */
- __u64_field(11, DRBD_GENLA_F_MANDATORY, bits_rs_total)
- __u64_field(12, DRBD_GENLA_F_MANDATORY, bits_rs_failed)
+ __u64_field(11, 0, bits_rs_total)
+ __u64_field(12, 0, bits_rs_failed)
/* for pre and post notifications of helper execution */
- __str_field(13, DRBD_GENLA_F_MANDATORY, helper, 32)
- __u32_field(14, DRBD_GENLA_F_MANDATORY, helper_exit_code)
+ __str_field(13, 0, helper, 32)
+ __u32_field(14, 0, helper_exit_code)
__u64_field(15, 0, send_cnt)
__u64_field(16, 0, recv_cnt)
@@ -233,12 +233,12 @@ GENL_struct(DRBD_NLA_STATE_INFO, 8, state_info,
)
GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms,
- __u64_field(1, DRBD_GENLA_F_MANDATORY, ov_start_sector)
- __u64_field(2, DRBD_GENLA_F_MANDATORY, ov_stop_sector)
+ __u64_field(1, 0, ov_start_sector)
+ __u64_field(2, 0, ov_stop_sector)
)
GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms,
- __flg_field(1, DRBD_GENLA_F_MANDATORY, clear_bm)
+ __flg_field(1, 0, clear_bm)
)
GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms,
@@ -246,11 +246,11 @@ GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms,
)
GENL_struct(DRBD_NLA_DISCONNECT_PARMS, 12, disconnect_parms,
- __flg_field(1, DRBD_GENLA_F_MANDATORY, force_disconnect)
+ __flg_field(1, 0, force_disconnect)
)
GENL_struct(DRBD_NLA_DETACH_PARMS, 13, detach_parms,
- __flg_field(1, DRBD_GENLA_F_MANDATORY, force_detach)
+ __flg_field(1, 0, force_detach)
)
GENL_struct(DRBD_NLA_RESOURCE_INFO, 15, resource_info,
@@ -315,12 +315,12 @@ GENL_struct(DRBD_NLA_PEER_DEVICE_STATISTICS, 22, peer_device_statistics,
)
GENL_struct(DRBD_NLA_NOTIFICATION_HEADER, 23, drbd_notification_header,
- __u32_field(1, DRBD_GENLA_F_MANDATORY, nh_type)
+ __u32_field(1, 0, nh_type)
)
GENL_struct(DRBD_NLA_HELPER, 24, drbd_helper_info,
- __str_field(1, DRBD_GENLA_F_MANDATORY, helper_name, 32)
- __u32_field(2, DRBD_GENLA_F_MANDATORY, helper_status)
+ __str_field(1, 0, helper_name, 32)
+ __u32_field(2, 0, helper_status)
)
/*
@@ -333,9 +333,9 @@ GENL_notification(
DRBD_EVENT, 1, events,
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
GENL_tla_expected(DRBD_NLA_STATE_INFO, DRBD_F_REQUIRED)
- GENL_tla_expected(DRBD_NLA_NET_CONF, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_DISK_CONF, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_SYNCER_CONF, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_NET_CONF, 0)
+ GENL_tla_expected(DRBD_NLA_DISK_CONF, 0)
+ GENL_tla_expected(DRBD_NLA_SYNCER_CONF, 0)
)
/* query kernel for specific or all info */
@@ -349,7 +349,7 @@ GENL_op(
),
/* To select the object .doit.
* Or a subset of objects in .dumpit. */
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0)
)
/* add DRBD minor devices as volumes to resources */
@@ -367,7 +367,7 @@ GENL_op(DRBD_ADM_DEL_RESOURCE, 8, GENL_doit(drbd_adm_del_resource),
GENL_op(DRBD_ADM_RESOURCE_OPTS, 9,
GENL_doit(drbd_adm_resource_opts),
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
- GENL_tla_expected(DRBD_NLA_RESOURCE_OPTS, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_RESOURCE_OPTS, 0)
)
GENL_op(
@@ -403,7 +403,7 @@ GENL_op(
DRBD_ADM_RESIZE, 13,
GENL_doit(drbd_adm_resize),
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
- GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_RESIZE_PARMS, 0)
)
GENL_op(
@@ -424,18 +424,18 @@ GENL_op(
DRBD_ADM_NEW_C_UUID, 16,
GENL_doit(drbd_adm_new_c_uuid),
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
- GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_NEW_C_UUID_PARMS, 0)
)
GENL_op(
DRBD_ADM_START_OV, 17,
GENL_doit(drbd_adm_start_ov),
- GENL_tla_expected(DRBD_NLA_START_OV_PARMS, DRBD_GENLA_F_MANDATORY)
+ GENL_tla_expected(DRBD_NLA_START_OV_PARMS, 0)
)
GENL_op(DRBD_ADM_DETACH, 18, GENL_doit(drbd_adm_detach),
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED)
- GENL_tla_expected(DRBD_NLA_DETACH_PARMS, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_DETACH_PARMS, 0))
GENL_op(DRBD_ADM_INVALIDATE, 19, GENL_doit(drbd_adm_invalidate),
GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_F_REQUIRED))
@@ -460,36 +460,36 @@ GENL_op(DRBD_ADM_GET_RESOURCES, 30,
GENL_op_init(
.dumpit = drbd_adm_dump_resources,
),
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0)
+ GENL_tla_expected(DRBD_NLA_RESOURCE_INFO, 0)
+ GENL_tla_expected(DRBD_NLA_RESOURCE_STATISTICS, 0))
GENL_op(DRBD_ADM_GET_DEVICES, 31,
GENL_op_init(
.dumpit = drbd_adm_dump_devices,
.done = drbd_adm_dump_devices_done,
),
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_DEVICE_INFO, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0)
+ GENL_tla_expected(DRBD_NLA_DEVICE_INFO, 0)
+ GENL_tla_expected(DRBD_NLA_DEVICE_STATISTICS, 0))
GENL_op(DRBD_ADM_GET_CONNECTIONS, 32,
GENL_op_init(
.dumpit = drbd_adm_dump_connections,
.done = drbd_adm_dump_connections_done,
),
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0)
+ GENL_tla_expected(DRBD_NLA_CONNECTION_INFO, 0)
+ GENL_tla_expected(DRBD_NLA_CONNECTION_STATISTICS, 0))
GENL_op(DRBD_ADM_GET_PEER_DEVICES, 33,
GENL_op_init(
.dumpit = drbd_adm_dump_peer_devices,
.done = drbd_adm_dump_peer_devices_done,
),
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, DRBD_GENLA_F_MANDATORY)
- GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0)
+ GENL_tla_expected(DRBD_NLA_PEER_DEVICE_INFO, 0)
+ GENL_tla_expected(DRBD_NLA_PEER_DEVICE_STATISTICS, 0))
GENL_notification(
DRBD_RESOURCE_STATE, 34, events,
@@ -524,7 +524,7 @@ GENL_op(
GENL_op_init(
.dumpit = drbd_adm_get_initial_state,
),
- GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, DRBD_GENLA_F_MANDATORY))
+ GENL_tla_expected(DRBD_NLA_CFG_CONTEXT, 0))
GENL_notification(
DRBD_HELPER, 40, events,
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 6edcac85155e..a7d36c9ea924 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -149,7 +149,8 @@ static int __ ## s_name ## _from_attrs(struct s_name *s, \
if (!tla) \
return -ENOMSG; \
DPRINT_TLA(#s_name, "<=-", #tag_name); \
- err = drbd_nla_parse_nested(ntb, maxtype, tla, s_name ## _nl_policy); \
+ err = nla_parse_nested_deprecated(ntb, maxtype, tla, \
+ s_name ## _nl_policy, NULL); \
if (err) \
return err; \
\
diff --git a/include/linux/genl_magic_struct.h b/include/linux/genl_magic_struct.h
index 621b87a87d74..2200cedd160a 100644
--- a/include/linux/genl_magic_struct.h
+++ b/include/linux/genl_magic_struct.h
@@ -25,16 +25,6 @@ extern void CONCATENATE(GENL_MAGIC_FAMILY, _genl_unregister)(void);
* Extension of genl attribute validation policies {{{2
*/
-/*
- * @DRBD_GENLA_F_MANDATORY: By default, netlink ignores attributes it does not
- * know about. This flag can be set in nlattr->nla_type to indicate that this
- * attribute must not be ignored.
- *
- * We check and remove this flag in drbd_nla_check_mandatory() before
- * validating the attribute types and lengths via nla_parse_nested().
- */
-#define DRBD_GENLA_F_MANDATORY (1 << 14)
-
/*
* Flags specific to drbd and not visible at the netlink layer, used in
* <struct>_from_attrs and <struct>_to_skb:
@@ -52,7 +42,6 @@ extern void CONCATENATE(GENL_MAGIC_FAMILY, _genl_unregister)(void);
#define DRBD_F_SENSITIVE (1 << 1)
#define DRBD_F_INVARIANT (1 << 2)
-#define __nla_type(x) ((__u16)((x) & NLA_TYPE_MASK & ~DRBD_GENLA_F_MANDATORY))
/* }}}1
* MAGIC
@@ -158,12 +147,12 @@ enum { \
#undef __field
#define __field(attr_nr, attr_flag, name, nla_type, type, \
__get, __put, __is_signed) \
- T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)),
+ T_ ## name = (__u16)(attr_nr),
#undef __array
#define __array(attr_nr, attr_flag, name, nla_type, type, \
maxlen, __get, __put, __is_signed) \
- T_ ## name = (__u16)(attr_nr | ((attr_flag) & DRBD_GENLA_F_MANDATORY)),
+ T_ ## name = (__u16)(attr_nr),
#include GENL_MAGIC_INCLUDE_FILE
base-commit: 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 00/20] DRBD 9 rework
From: Jens Axboe @ 2026-04-03 13:26 UTC (permalink / raw)
To: drbd-dev, linux-kernel, Lars Ellenberg, Philipp Reisner,
linux-block
In-Reply-To: <ac-_fAsaSk-E_80R@localhost.localdomain>
On 4/3/26 7:24 AM, Christoph B?hmwalder wrote:
> On Thu, Apr 02, 2026 at 07:30:35PM -0600, Jens Axboe wrote:
>> On 3/27/26 4:38 PM, Christoph B?hmwalder wrote:
>>> As discussed (context: [0]), here is the first version of our DRBD 9
>>> rework series, intended for for-next via for-7.1/drbd.
>>
>> Will you fixup the kerneldoc (nits) and the assigned-but-not-read
>> issues and send out a new version? Also looks this series doesn't
>> actually apply to for-7.1/block, patch 12 fails.
>>
>> --
>> Jens Axboe
>
> Right, the recent genl changes now cause a conflict. I'm rebasing now.
> The nits are already incorporated and will land with v2.
>
> Just for my own planning: what does your timing cycle look like for the
> -next branch? I assume you also want to have that ready before the merge
> window opens? Or is the schedule for -next more liberal?
There's no timing for that branch, it always exists and has whatever is
pending for both the current and next release. Since linux-next rebases
every day, my for-next is also quite often rebased as it's just pulling
in everything that is pending. Hence there's no timing to worry about
here, it'll get updated daily basically as patches flow into various
branches.
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH 00/20] DRBD 9 rework
From: Christoph Böhmwalder @ 2026-04-03 13:24 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-kernel, Lars Ellenberg, Philipp Reisner,
linux-block
In-Reply-To: <ecf00b4b-c3f8-4161-a97d-3d23b423cabf@kernel.dk>
On Thu, Apr 02, 2026 at 07:30:35PM -0600, Jens Axboe wrote:
>On 3/27/26 4:38 PM, Christoph Böhmwalder wrote:
>> As discussed (context: [0]), here is the first version of our DRBD 9
>> rework series, intended for for-next via for-7.1/drbd.
>
>Will you fixup the kerneldoc (nits) and the assigned-but-not-read
>issues and send out a new version? Also looks this series doesn't
>actually apply to for-7.1/block, patch 12 fails.
>
>--
>Jens Axboe
Right, the recent genl changes now cause a conflict. I'm rebasing now.
The nits are already incorporated and will land with v2.
Just for my own planning: what does your timing cycle look like for the
-next branch? I assume you also want to have that ready before the merge
window opens? Or is the schedule for -next more liberal?
Thanks,
Christoph
^ permalink raw reply
* Re: [PATCH RESEND] block: use sysfs_emit in sysfs show functions
From: Jens Axboe @ 2026-04-03 11:11 UTC (permalink / raw)
To: Kees Cook, Thorsten Blum; +Cc: linux-block, linux-kernel
In-Reply-To: <20260402164958.894879-4-thorsten.blum@linux.dev>
On Thu, 02 Apr 2026 18:50:00 +0200, Thorsten Blum wrote:
> Replace sprintf() with sysfs_emit() in sysfs show functions.
> sysfs_emit() is preferred for formatting sysfs output because it
> provides safer bounds checking.
Applied, thanks!
[1/1] block: use sysfs_emit in sysfs show functions
commit: a175ee8273319547a4be7584da03831a2fb2f835
Best regards,
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH 6.1.y v2 0/6] nvme: correctly fix admin request_queue lifetime
From: Fedor Pchelkin @ 2026-04-03 9:48 UTC (permalink / raw)
To: Heyne, Maximilian, stable@vger.kernel.org
Cc: Jens Axboe, Hector Martin, Sven Peter, Alyssa Rosenzweig,
Keith Busch, Christoph Hellwig, Sagi Grimberg,
James E.J. Bottomley, Martin K. Petersen, Alim Akhtar,
Avri Altman, Bart Van Assche, Sasha Levin, Peter Wang,
Greg Kroah-Hartman, Adrian Hunter, Seunghwan Baek, Seunghui Lee,
Thomas Yen, Brian Kao, Sanjeev Yadav, Wonkon Kim,
Chaitanya Kulkarni, Hannes Reinecke, Ming Lei,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org
In-Reply-To: <20260402-moral-jockey-f072379b@mheyne-amazon>
"Heyne, Maximilian" <mheyne@amazon.de> wrote:
> The initial attempt to backport upstream commit 03b3bcd319b3 ("nvme: fix
> admin request_queue lifetime") was not correct leading to refcount
> underflows and not even fixing the problem.
>
> I've tested the reproduction steps from [1] (adding a delay to
> nvme_submit_user_cmd and 'echo 1 | sudo tee
> /sys/class/nvme/nvme0/delete_controller') on the nvme-tcp driver which
> printed the KASAN UAF blurb.
>
> Fixing the issue in the 6.1 series requires a few dependent patches.
> This is mainly the upstream commit 2b3f056f72e5 ("blk-mq: move the call
> to blk_put_queue out of blk_mq_destroy_queue") which allows to move the
> blk_put_queue to a different location.
>
> The backport of commit 03b3bcd319b3 ("nvme: fix admin
> request_queue lifetime") needed a tweak to the nvme pci driver.
>
> Furthermore, in this patch series I've also included a follow-up fixup
> from upstream commit b84bb7bd913d ("nvme: fix admin queue leak on
> controller reset"), again with an adaption to the nvme pci driver. This
> issue could easily be reproduced by resetting the controller (no need to
> run full blktests):
>
> echo 1 > /sys/class/nvme/nvme0/reset_controller
For the series
Tested-by: Fedor Pchelkin <pchelkin@ispras.ru>
Thanks for the prompt fix.
^ permalink raw reply
* Re: [PATCH 6.1.y v2 6/6] nvme: fix admin queue leak on controller reset
From: Fedor Pchelkin @ 2026-04-03 9:43 UTC (permalink / raw)
To: Heyne, Maximilian
Cc: stable@vger.kernel.org, Ming Lei, Keith Busch, Yi Zhang,
Jens Axboe, Hector Martin, Sven Peter, Alyssa Rosenzweig,
Christoph Hellwig, Sagi Grimberg, James E.J. Bottomley,
Martin K. Petersen, Alim Akhtar, Avri Altman, Bart Van Assche,
Sasha Levin, Peter Wang, Greg Kroah-Hartman, Seunghwan Baek,
Seunghui Lee, Adrian Hunter, Brian Kao, Sanjeev Yadav, Wonkon Kim,
Chaitanya Kulkarni, Hannes Reinecke, linux-block@vger.kernel.org,
linux-kernel@vger.kernel.org, asahi@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org
In-Reply-To: <20260402-fox-attic-82ebf113@mheyne-amazon>
"Heyne, Maximilian" <mheyne@amazon.de>
> [ Have to do analogous work in nvme_pci_alloc_admin_tag_set in pci.c due
> to missing upstream commit 0da7feaa5913 ("nvme-pci: use the tagset
> alloc/free helpers") ]
nit: not actually needed for 6.1.y because the only callsite of
nvme_pci_alloc_admin_tag_set() there looks like
if (!dev->ctrl.admin_q) {
result = nvme_pci_alloc_admin_tag_set(dev);
Though that doesn't really matter and not worth resending I think.
^ permalink raw reply
* Re: [PATCH 6.1.y 5/8] nvme-apple: remove an extra queue reference
From: Fedor Pchelkin @ 2026-04-03 9:35 UTC (permalink / raw)
To: Heyne, Maximilian
Cc: Christoph Hellwig, Sagi Grimberg, stable@vger.kernel.org,
Sven Peter, Chaitanya Kulkarni, Keith Busch, Jens Axboe,
Hector Martin, Alyssa Rosenzweig, James E.J. Bottomley,
Martin K. Petersen, Alim Akhtar, Avri Altman, Bart Van Assche,
Sasha Levin, Peter Wang, Greg Kroah-Hartman, Seunghui Lee,
Sanjeev Yadav, Wonkon Kim, Brian Kao, Hannes Reinecke, Ming Lei,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-nvme@lists.infradead.org, linux-scsi@vger.kernel.org
In-Reply-To: <20260402-anti-cuba-1ea02cea@mheyne-amazon>
On Thu, 02. Apr 12:31, Heyne, Maximilian wrote:
> On Wed, Apr 01, 2026 at 11:45:57PM +0300, Fedor Pchelkin wrote:
> > Hello,
> >
> > "Heyne, Maximilian" <mheyne@amazon.de> wrote:
> > > From: Christoph Hellwig <hch@lst.de>
> > >
> > > [ Upstream commit 941f7298c70c7668416e7845fa76eb72c07d966b ]
> > >
> > > Now that blk_mq_destroy_queue does not release the queue reference, there
> > > is no need for a second admin queue reference to be held by the
> > > apple_nvme structure.
> >
> > This patch is probably buggy in upstream. It removes extra reference
> > ->get, but doesn't remove the corresponding ->put which is located
> > inside apple_nvme_free_ctrl().
>
> Now I'm seeing this as well. Has the same problem as the pci driver in
> 6.1 where blk_put_queue is called from nvme_free_ctrl() and again from
> apple_nvme_free_ctrl(). Thank you for catching this. I don't have the
> hardware to test this.
>
> Are you going to send a fix upstream? It's looks to be broken on master,
> too.
I don't have the needed hardware either but will send the patch for review.
> >
> > That said, the other part of the backport series FWIW looks good to me,
> > and I've also verified it resolves the 6.1.y regression.
>
> You may leave a Tested-by if you want ;-)
I'll leave it for v2 then.
^ permalink raw reply
* Re: [bug report]nvmet_auth kmemleak observed during blktests
From: Maurizio Lombardi @ 2026-04-03 9:21 UTC (permalink / raw)
To: Yi Zhang, linux-block, open list:NVM EXPRESS DRIVER; +Cc: Shinichiro Kawasaki
In-Reply-To: <CAHj4cs-u3MWQR4idywptMfjEYi4YwObWFx4KVib35dZ5HMBDdw@mail.gmail.com>
On Fri Apr 3, 2026 at 10:46 AM CEST, Yi Zhang wrote:
> Hi
>
> I found the following kmemleak during blktests on the
> linux-block/for-next, please help check it and let me know if you need
> any test/info for it, thanks.
>
> commit:
> aac56c7b77fa (HEAD -> for-next, origin/for-next) Merge branch
> 'for-7.1/io_uring' into for-next
>
> reproducer:
> nvme_trtype=loop ./check nvme/041 nvme/042 nvme/043 nvme/044 nvme/045
> nvme/051 nvme/052
>
> kmemleak:
> unreferenced object 0xff11000305c48240 (size 32):
> comm "kworker/u48:3", pid 123223, jiffies 4401374163
> hex dump (first 32 bytes):
> 30 1e 78 66 9b 04 e7 4a d5 d7 a3 a2 ab 1f f1 22 0.xf...J......."
> 11 4a aa 11 b5 f7 fa f6 24 a6 17 11 e6 f8 e7 dc .J......$.......
> backtrace (crc 58405ce8):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_challenge+0x329/0x9f0 [nvmet]
> nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
Maybe this has been introduced by commit 2e6eb6b277f5
("nvmet-tcp: Don't free SQ on authentication success")
If nvmet_execute_auth_receive() gets called twice and executes
nvmet_auth_challenge(), the dhchap_c1 pointer is leaked.
Maurizio
> unreferenced object 0xff1100027be14c00 (size 256):
> comm "kworker/u48:3", pid 123223, jiffies 4401374168
> hex dump (first 32 bytes):
> 30 96 ec 83 33 bb fc 41 ec 81 70 14 1e ad 32 fd 0...3..A..p...2.
> 39 b8 ca 9c 99 22 ff 28 f0 80 f3 e0 1d 82 36 a9 9....".(......6.
> backtrace (crc e365275d):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
> nvmet_auth_reply+0x436/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000305c48d40 (size 32):
> comm "kworker/u48:3", pid 123223, jiffies 4401374170
> hex dump (first 32 bytes):
> c0 8b 24 c4 c1 5a 37 d1 fc 49 ec 3e 44 05 7e 19 ..$..Z7..I.>D.~.
> 70 39 6a d0 53 22 6d 23 fc b9 94 83 e3 3a 60 e2 p9j.S"m#.....:`.
> backtrace (crc 8284cf12):
> __kmalloc_node_track_caller_noprof+0x637/0x880
> kmemdup_noprof+0x22/0x50
> nvmet_auth_reply+0x2ba/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff1100016dd8c7c0 (size 32):
> comm "kworker/u48:2", pid 139664, jiffies 4401374600
> hex dump (first 32 bytes):
> 21 1e e5 a0 b9 e6 a0 6b 85 cb 62 ff 30 d6 21 0f !......k..b.0.!.
> 05 89 bc 6a 44 fe 2a c4 bd 35 23 59 6c 56 2b 2e ...jD.*..5#YlV+.
> backtrace (crc e32fd56c):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_challenge+0x329/0x9f0 [nvmet]
> nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000255549600 (size 256):
> comm "kworker/u48:2", pid 139664, jiffies 4401374604
> hex dump (first 32 bytes):
> 11 1a 6e 99 d1 bc ae 48 5d aa f1 74 62 30 68 c4 ..n....H]..tb0h.
> 07 9f 31 dc 83 a4 a4 92 47 18 9c 04 1e 7d 68 c1 ..1.....G....}h.
> backtrace (crc db3ad817):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
> nvmet_auth_reply+0x436/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff1100016dd8cc00 (size 32):
> comm "kworker/u48:2", pid 139664, jiffies 4401374609
> hex dump (first 32 bytes):
> 51 ff e9 8e 10 6b b4 b3 3f 6c 7d f2 74 eb 42 98 Q....k..?l}.t.B.
> 6c f8 ab ec 10 d6 e8 0f 02 79 4a e4 ec b2 ce ed l........yJ.....
> backtrace (crc 7099040d):
> __kmalloc_node_track_caller_noprof+0x637/0x880
> kmemdup_noprof+0x22/0x50
> nvmet_auth_reply+0x2ba/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff1100025554a800 (size 256):
> comm "kworker/u48:2", pid 139664, jiffies 4401374633
> hex dump (first 32 bytes):
> eb a9 ed 0e b7 42 c6 6c 48 ee 56 29 a4 8a 99 18 .....B.lH.V)....
> 1c 90 2a 53 22 7a ee 5a c0 6e 60 43 5b 33 a1 d2 ..*S"z.Z.n`C[3..
> backtrace (crc 3ce24e58):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
> nvmet_auth_reply+0x436/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000267237a80 (size 32):
> comm "kworker/u48:2", pid 139664, jiffies 4401374635
> hex dump (first 32 bytes):
> 20 25 77 95 60 f2 19 5a 09 20 2c 25 8b 04 2a 4b %w.`..Z. ,%..*K
> b9 53 8e 10 39 b9 07 0d e0 fc 93 3f 82 50 86 0c .S..9......?.P..
> backtrace (crc 3f42440d):
> __kmalloc_node_track_caller_noprof+0x637/0x880
> kmemdup_noprof+0x22/0x50
> nvmet_auth_reply+0x2ba/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000138f46e40 (size 32):
> comm "kworker/u48:2", pid 139664, jiffies 4401374654
> hex dump (first 32 bytes):
> 2d da 99 66 3b e7 d6 65 aa d7 1f a6 51 b4 ab 19 -..f;..e....Q...
> 46 d7 30 0d 12 fd 55 90 c4 6a 4a 7a b8 55 7f 4f F.0...U..jJz.U.O
> backtrace (crc 3ab35d56):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_challenge+0x329/0x9f0 [nvmet]
> nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000126860400 (size 256):
> comm "kworker/u48:2", pid 139664, jiffies 4401374658
> hex dump (first 32 bytes):
> cb 48 8c 49 58 82 bd fd 21 5b e4 a5 5b 5e 7b 8b .H.IX...![..[^{.
> 48 6a 47 3e 9f b7 76 06 c8 47 6a 5f 3e b4 20 15 HjG>..v..Gj_>. .
> backtrace (crc b164cda1):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
> nvmet_auth_reply+0x436/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000138f468c0 (size 32):
> comm "kworker/u48:2", pid 139664, jiffies 4401374662
> hex dump (first 32 bytes):
> 01 dd af 3b af a0 f8 ec 61 80 c4 aa ad 56 9a 27 ...;....a....V.'
> d4 f9 f9 8d 98 64 ce 5a 81 e2 14 e0 e3 5c 79 97 .....d.Z.....\y.
> backtrace (crc b24f43c2):
> __kmalloc_node_track_caller_noprof+0x637/0x880
> kmemdup_noprof+0x22/0x50
> nvmet_auth_reply+0x2ba/0xd00 [nvmet]
> nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
> unreferenced object 0xff11000185c80580 (size 64):
> comm "kworker/u48:2", pid 139664, jiffies 4401374716
> hex dump (first 32 bytes):
> bf a4 73 5a 5c a7 d7 8e f7 6e f9 39 3a 94 66 a4 ..sZ\....n.9:.f.
> 8e f9 bc f6 9a 23 ac dc c8 71 85 ef 09 4c ac 38 .....#...q...L.8
> backtrace (crc 70f5e8bf):
> __kmalloc_noprof+0x635/0x870
> nvmet_auth_challenge+0x329/0x9f0 [nvmet]
> nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
> process_one_work+0xd98/0x1390
> worker_thread+0x60b/0x1000
> kthread+0x36c/0x470
> ret_from_fork+0x5dc/0x8e0
> ret_from_fork_asm+0x1a/0x30
^ permalink raw reply
* [bug report]nvmet_auth kmemleak observed during blktests
From: Yi Zhang @ 2026-04-03 8:46 UTC (permalink / raw)
To: linux-block, open list:NVM EXPRESS DRIVER; +Cc: Shinichiro Kawasaki
Hi
I found the following kmemleak during blktests on the
linux-block/for-next, please help check it and let me know if you need
any test/info for it, thanks.
commit:
aac56c7b77fa (HEAD -> for-next, origin/for-next) Merge branch
'for-7.1/io_uring' into for-next
reproducer:
nvme_trtype=loop ./check nvme/041 nvme/042 nvme/043 nvme/044 nvme/045
nvme/051 nvme/052
kmemleak:
unreferenced object 0xff11000305c48240 (size 32):
comm "kworker/u48:3", pid 123223, jiffies 4401374163
hex dump (first 32 bytes):
30 1e 78 66 9b 04 e7 4a d5 d7 a3 a2 ab 1f f1 22 0.xf...J......."
11 4a aa 11 b5 f7 fa f6 24 a6 17 11 e6 f8 e7 dc .J......$.......
backtrace (crc 58405ce8):
__kmalloc_noprof+0x635/0x870
nvmet_auth_challenge+0x329/0x9f0 [nvmet]
nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff1100027be14c00 (size 256):
comm "kworker/u48:3", pid 123223, jiffies 4401374168
hex dump (first 32 bytes):
30 96 ec 83 33 bb fc 41 ec 81 70 14 1e ad 32 fd 0...3..A..p...2.
39 b8 ca 9c 99 22 ff 28 f0 80 f3 e0 1d 82 36 a9 9....".(......6.
backtrace (crc e365275d):
__kmalloc_noprof+0x635/0x870
nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
nvmet_auth_reply+0x436/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000305c48d40 (size 32):
comm "kworker/u48:3", pid 123223, jiffies 4401374170
hex dump (first 32 bytes):
c0 8b 24 c4 c1 5a 37 d1 fc 49 ec 3e 44 05 7e 19 ..$..Z7..I.>D.~.
70 39 6a d0 53 22 6d 23 fc b9 94 83 e3 3a 60 e2 p9j.S"m#.....:`.
backtrace (crc 8284cf12):
__kmalloc_node_track_caller_noprof+0x637/0x880
kmemdup_noprof+0x22/0x50
nvmet_auth_reply+0x2ba/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff1100016dd8c7c0 (size 32):
comm "kworker/u48:2", pid 139664, jiffies 4401374600
hex dump (first 32 bytes):
21 1e e5 a0 b9 e6 a0 6b 85 cb 62 ff 30 d6 21 0f !......k..b.0.!.
05 89 bc 6a 44 fe 2a c4 bd 35 23 59 6c 56 2b 2e ...jD.*..5#YlV+.
backtrace (crc e32fd56c):
__kmalloc_noprof+0x635/0x870
nvmet_auth_challenge+0x329/0x9f0 [nvmet]
nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000255549600 (size 256):
comm "kworker/u48:2", pid 139664, jiffies 4401374604
hex dump (first 32 bytes):
11 1a 6e 99 d1 bc ae 48 5d aa f1 74 62 30 68 c4 ..n....H]..tb0h.
07 9f 31 dc 83 a4 a4 92 47 18 9c 04 1e 7d 68 c1 ..1.....G....}h.
backtrace (crc db3ad817):
__kmalloc_noprof+0x635/0x870
nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
nvmet_auth_reply+0x436/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff1100016dd8cc00 (size 32):
comm "kworker/u48:2", pid 139664, jiffies 4401374609
hex dump (first 32 bytes):
51 ff e9 8e 10 6b b4 b3 3f 6c 7d f2 74 eb 42 98 Q....k..?l}.t.B.
6c f8 ab ec 10 d6 e8 0f 02 79 4a e4 ec b2 ce ed l........yJ.....
backtrace (crc 7099040d):
__kmalloc_node_track_caller_noprof+0x637/0x880
kmemdup_noprof+0x22/0x50
nvmet_auth_reply+0x2ba/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff1100025554a800 (size 256):
comm "kworker/u48:2", pid 139664, jiffies 4401374633
hex dump (first 32 bytes):
eb a9 ed 0e b7 42 c6 6c 48 ee 56 29 a4 8a 99 18 .....B.lH.V)....
1c 90 2a 53 22 7a ee 5a c0 6e 60 43 5b 33 a1 d2 ..*S"z.Z.n`C[3..
backtrace (crc 3ce24e58):
__kmalloc_noprof+0x635/0x870
nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
nvmet_auth_reply+0x436/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000267237a80 (size 32):
comm "kworker/u48:2", pid 139664, jiffies 4401374635
hex dump (first 32 bytes):
20 25 77 95 60 f2 19 5a 09 20 2c 25 8b 04 2a 4b %w.`..Z. ,%..*K
b9 53 8e 10 39 b9 07 0d e0 fc 93 3f 82 50 86 0c .S..9......?.P..
backtrace (crc 3f42440d):
__kmalloc_node_track_caller_noprof+0x637/0x880
kmemdup_noprof+0x22/0x50
nvmet_auth_reply+0x2ba/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000138f46e40 (size 32):
comm "kworker/u48:2", pid 139664, jiffies 4401374654
hex dump (first 32 bytes):
2d da 99 66 3b e7 d6 65 aa d7 1f a6 51 b4 ab 19 -..f;..e....Q...
46 d7 30 0d 12 fd 55 90 c4 6a 4a 7a b8 55 7f 4f F.0...U..jJz.U.O
backtrace (crc 3ab35d56):
__kmalloc_noprof+0x635/0x870
nvmet_auth_challenge+0x329/0x9f0 [nvmet]
nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000126860400 (size 256):
comm "kworker/u48:2", pid 139664, jiffies 4401374658
hex dump (first 32 bytes):
cb 48 8c 49 58 82 bd fd 21 5b e4 a5 5b 5e 7b 8b .H.IX...![..[^{.
48 6a 47 3e 9f b7 76 06 c8 47 6a 5f 3e b4 20 15 HjG>..v..Gj_>. .
backtrace (crc b164cda1):
__kmalloc_noprof+0x635/0x870
nvmet_auth_ctrl_sesskey+0xfa/0x3a0 [nvmet]
nvmet_auth_reply+0x436/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000138f468c0 (size 32):
comm "kworker/u48:2", pid 139664, jiffies 4401374662
hex dump (first 32 bytes):
01 dd af 3b af a0 f8 ec 61 80 c4 aa ad 56 9a 27 ...;....a....V.'
d4 f9 f9 8d 98 64 ce 5a 81 e2 14 e0 e3 5c 79 97 .....d.Z.....\y.
backtrace (crc b24f43c2):
__kmalloc_node_track_caller_noprof+0x637/0x880
kmemdup_noprof+0x22/0x50
nvmet_auth_reply+0x2ba/0xd00 [nvmet]
nvmet_execute_auth_send+0xc7f/0x14f0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
unreferenced object 0xff11000185c80580 (size 64):
comm "kworker/u48:2", pid 139664, jiffies 4401374716
hex dump (first 32 bytes):
bf a4 73 5a 5c a7 d7 8e f7 6e f9 39 3a 94 66 a4 ..sZ\....n.9:.f.
8e f9 bc f6 9a 23 ac dc c8 71 85 ef 09 4c ac 38 .....#...q...L.8
backtrace (crc 70f5e8bf):
__kmalloc_noprof+0x635/0x870
nvmet_auth_challenge+0x329/0x9f0 [nvmet]
nvmet_execute_auth_receive+0x381/0x7b0 [nvmet]
process_one_work+0xd98/0x1390
worker_thread+0x60b/0x1000
kthread+0x36c/0x470
ret_from_fork+0x5dc/0x8e0
ret_from_fork_asm+0x1a/0x30
--
Best Regards,
Yi Zhang
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox