nbd: factor out a helper to get nbd_config without holding 'config_lock'
authorLi Nan <linan122@huawei.com>
Thu, 16 Nov 2023 16:23:15 +0000 (00:23 +0800)
committerJens Axboe <axboe@kernel.dk>
Mon, 20 Nov 2023 17:16:44 +0000 (10:16 -0700)
There are no functional changes, just to make code cleaner and prepare
to fix null-ptr-dereference while accessing 'nbd->config'.

Signed-off-by: Li Nan <linan122@huawei.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Link: https://lore.kernel.org/r/20231116162316.1740402-3-linan666@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/nbd.c

index 02f844832d912c13486d016771ddf2972eadf374..daaf8805e876c2a6ec0f2cec61a41b30c934e0a4 100644 (file)
@@ -395,6 +395,14 @@ static u32 req_to_nbd_cmd_type(struct request *req)
        }
 }
 
+static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
+{
+       if (refcount_inc_not_zero(&nbd->config_refs))
+               return nbd->config;
+
+       return NULL;
+}
+
 static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
@@ -409,13 +417,13 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
                return BLK_EH_DONE;
        }
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                cmd->status = BLK_STS_TIMEOUT;
                __clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
                mutex_unlock(&cmd->lock);
                goto done;
        }
-       config = nbd->config;
 
        if (config->num_connections > 1 ||
            (config->num_connections == 1 && nbd->tag_set.timeout)) {
@@ -977,12 +985,12 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
        struct nbd_sock *nsock;
        int ret;
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                dev_err_ratelimited(disk_to_dev(nbd->disk),
                                    "Socks array is empty\n");
                return -EINVAL;
        }
-       config = nbd->config;
 
        if (index >= config->num_connections) {
                dev_err_ratelimited(disk_to_dev(nbd->disk),
@@ -1560,6 +1568,7 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd)
 static int nbd_open(struct gendisk *disk, blk_mode_t mode)
 {
        struct nbd_device *nbd;
+       struct nbd_config *config;
        int ret = 0;
 
        mutex_lock(&nbd_index_mutex);
@@ -1572,7 +1581,9 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode)
                ret = -ENXIO;
                goto out;
        }
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                mutex_lock(&nbd->config_lock);
                if (refcount_inc_not_zero(&nbd->config_refs)) {
                        mutex_unlock(&nbd->config_lock);
@@ -1588,7 +1599,7 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode)
                mutex_unlock(&nbd->config_lock);
                if (max_part)
                        set_bit(GD_NEED_PART_SCAN, &disk->state);
-       } else if (nbd_disconnected(nbd->config)) {
+       } else if (nbd_disconnected(config)) {
                if (max_part)
                        set_bit(GD_NEED_PART_SCAN, &disk->state);
        }
@@ -2205,7 +2216,8 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
        }
        mutex_unlock(&nbd_index_mutex);
 
-       if (!refcount_inc_not_zero(&nbd->config_refs)) {
+       config = nbd_get_config_unlocked(nbd);
+       if (!config) {
                dev_err(nbd_to_dev(nbd),
                        "not configured, cannot reconfigure\n");
                nbd_put(nbd);
@@ -2213,7 +2225,6 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
        }
 
        mutex_lock(&nbd->config_lock);
-       config = nbd->config;
        if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) ||
            !nbd->pid) {
                dev_err(nbd_to_dev(nbd),