diff options
author | Christoph Hellwig <hch@lst.de> | 2021-08-25 18:31:04 +0200 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2021-08-25 14:20:20 -0600 |
commit | 409e0ff10ead30a620ee48acb6d4545d9cb95359 (patch) | |
tree | 3c02a40a9915c593b978fb93765df45e8ca372a0 /drivers/block | |
parent | 93f63bc41f699318807df202a175d564c26bda87 (diff) | |
download | linux-409e0ff10ead30a620ee48acb6d4545d9cb95359.tar.gz linux-409e0ff10ead30a620ee48acb6d4545d9cb95359.tar.bz2 linux-409e0ff10ead30a620ee48acb6d4545d9cb95359.zip |
nbd: reset NBD to NULL when restarting in nbd_genl_connect
When nbd_genl_connect restarts to wait for a disconnecting device, nbd
needs to be reset to NULL. Do that by facoring out a helper to find
an unused device.
Fixes: 6177b56c96ff ("nbd: refactor device search and allocation in nbd_genl_connect")
Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Reported-by: Hillf Danton <hdanton@sina.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210825163108.50713-3-hch@lst.de
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nbd.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 0c1389da3066..938ca7f5a11f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1781,6 +1781,20 @@ out: return ERR_PTR(err); } +static struct nbd_device *nbd_find_unused(void) +{ + struct nbd_device *nbd; + int id; + + lockdep_assert_held(&nbd_index_mutex); + + idr_for_each_entry(&nbd_index_idr, nbd, id) + if (!refcount_read(&nbd->config_refs)) + return nbd; + + return NULL; +} + /* Netlink interface. */ static const struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] = { [NBD_ATTR_INDEX] = { .type = NLA_U32 }, @@ -1828,7 +1842,7 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd) static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) { DECLARE_COMPLETION_ONSTACK(destroy_complete); - struct nbd_device *nbd = NULL; + struct nbd_device *nbd; struct nbd_config *config; int index = -1; int ret; @@ -1849,20 +1863,10 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) } again: mutex_lock(&nbd_index_mutex); - if (index == -1) { - struct nbd_device *tmp; - int id; - - idr_for_each_entry(&nbd_index_idr, tmp, id) { - if (!refcount_read(&tmp->config_refs)) { - nbd = tmp; - break; - } - } - } else { + if (index == -1) + nbd = nbd_find_unused(); + else nbd = idr_find(&nbd_index_idr, index); - } - if (nbd) { if (test_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags) && test_bit(NBD_DISCONNECT_REQUESTED, &nbd->flags)) { |