nvme: make nvme_identify_ns propagate errors back
authorSagi Grimberg <sagi@grimberg.me>
Sat, 3 Aug 2019 01:11:42 +0000 (18:11 -0700)
committerSagi Grimberg <sagi@grimberg.me>
Thu, 12 Sep 2019 15:50:45 +0000 (08:50 -0700)
right now callers of nvme_identify_ns only know that it failed,
but don't know why. Make nvme_identify_ns propagate the error back.
Because nvme_submit_sync_cmd may return a positive status code, we
make nvme_identify_ns receive the id by reference and return that
status up the call chain, but make sure not to leak positive nvme
status codes to the upper layers.

Reviewed-by: Minwoo Im <minwoo.im.dev@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Sagi Grimberg <sagi@grimberg.me>
drivers/nvme/host/core.c

index 2797d38d2dcad9343aafa06cd96390e6e055bffc..52b453e4ae9c4666c2d1fb7d85a87fffea7e1905 100644 (file)
@@ -1096,10 +1096,9 @@ static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *n
                                    NVME_IDENTIFY_DATA_SIZE);
 }
 
-static struct nvme_id_ns *nvme_identify_ns(struct nvme_ctrl *ctrl,
-               unsigned nsid)
+static int nvme_identify_ns(struct nvme_ctrl *ctrl,
+               unsigned nsid, struct nvme_id_ns **id)
 {
-       struct nvme_id_ns *id;
        struct nvme_command c = { };
        int error;
 
@@ -1108,18 +1107,17 @@ static struct nvme_id_ns *nvme_identify_ns(struct nvme_ctrl *ctrl,
        c.identify.nsid = cpu_to_le32(nsid);
        c.identify.cns = NVME_ID_CNS_NS;
 
-       id = kmalloc(sizeof(*id), GFP_KERNEL);
-       if (!id)
-               return NULL;
+       *id = kmalloc(sizeof(**id), GFP_KERNEL);
+       if (!*id)
+               return -ENOMEM;
 
-       error = nvme_submit_sync_cmd(ctrl->admin_q, &c, id, sizeof(*id));
+       error = nvme_submit_sync_cmd(ctrl->admin_q, &c, *id, sizeof(**id));
        if (error) {
                dev_warn(ctrl->device, "Identify namespace failed (%d)\n", error);
-               kfree(id);
-               return NULL;
+               kfree(*id);
        }
 
-       return id;
+       return error;
 }
 
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
@@ -1740,13 +1738,13 @@ static int nvme_revalidate_disk(struct gendisk *disk)
                return -ENODEV;
        }
 
-       id = nvme_identify_ns(ctrl, ns->head->ns_id);
-       if (!id)
-               return -ENODEV;
+       ret = nvme_identify_ns(ctrl, ns->head->ns_id, &id);
+       if (ret)
+               goto out;
 
        if (id->ncap == 0) {
                ret = -ENODEV;
-               goto out;
+               goto free_id;
        }
 
        __nvme_revalidate_disk(disk, id);
@@ -1757,8 +1755,11 @@ static int nvme_revalidate_disk(struct gendisk *disk)
                ret = -ENODEV;
        }
 
-out:
+free_id:
        kfree(id);
+out:
+       if (ret > 0)
+               ret = blk_status_to_errno(nvme_error_status(ret));
        return ret;
 }
 
@@ -3329,11 +3330,9 @@ static int nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
        nvme_set_queue_limits(ctrl, ns->queue);
 
-       id = nvme_identify_ns(ctrl, nsid);
-       if (!id) {
-               ret = -EIO;
+       ret = nvme_identify_ns(ctrl, nsid, &id);
+       if (ret)
                goto out_free_queue;
-       }
 
        if (id->ncap == 0) {
                ret = -EINVAL;
@@ -3395,6 +3394,8 @@ static int nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        blk_cleanup_queue(ns->queue);
  out_free_ns:
        kfree(ns);
+       if (ret > 0)
+               ret = blk_status_to_errno(nvme_error_status(ret));
        return ret;
 }