From: Jackie Liu <[email protected]>

nbd_start_device() drops config_lock while updating the hardware queue
count. Two NBD_DO_IT callers can pass the initial nbd->pid check before
either caller publishes its PID.

After the first caller starts the device, the second caller overwrites
nbd->pid and fails to create the existing sysfs pid attribute with
-EEXIST. The running device then reports the losing caller's PID.

Recheck nbd->pid after reacquiring config_lock and return -EBUSY if
another caller has already started the device. Do this before retrying
the queue update or changing any startup state.

Fixes: 8b428f42f3ed ("nbd: fix lockdep deadlock warning")
Cc: [email protected] # v6.17+
Signed-off-by: Jackie Liu <[email protected]>
---
 drivers/block/nbd.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index ffce519bf008..e8e8517fb6c7 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1530,6 +1530,10 @@ static int nbd_start_device(struct nbd_device *nbd)
        blk_mq_update_nr_hw_queues(&nbd->tag_set, num_connections);
        mutex_lock(&nbd->config_lock);
 
+       /* The device may have been started or reconfigured while unlocked. */
+       if (nbd->pid)
+               return -EBUSY;
+
        /* if another code path updated nr_hw_queues, retry until succeed */
        if (num_connections != config->num_connections) {
                num_connections = config->num_connections;

Reply via email to