nvmet: make sn stable once connection was established
authorNoam Gottlieb <ngottlieb@nvidia.com>
Mon, 7 Jun 2021 09:23:22 +0000 (12:23 +0300)
committerChristoph Hellwig <hch@lst.de>
Thu, 17 Jun 2021 13:51:19 +0000 (15:51 +0200)
Once some host has connected to the target, make sure that the serial
number is stable and cannot be changed.

Reviewed-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Signed-off-by: Noam Gottlieb <ngottlieb@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/configfs.c
drivers/nvme/target/nvmet.h

index 9c73dbf..5f15c32 100644 (file)
@@ -337,6 +337,12 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
        u32 cmd_capsule_size;
        u16 status = 0;
 
+       if (!subsys->subsys_discovered) {
+               mutex_lock(&subsys->lock);
+               subsys->subsys_discovered = true;
+               mutex_unlock(&subsys->lock);
+       }
+
        /*
         * If there is no model number yet, set it now.  It will then remain
         * stable for the life time of the subsystem.
index 027b28a..a13da86 100644 (file)
@@ -1044,12 +1044,18 @@ static ssize_t nvmet_subsys_attr_serial_show(struct config_item *item,
        return snprintf(page, PAGE_SIZE, "%s\n", subsys->serial);
 }
 
-static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
-                                             const char *page, size_t count)
+static ssize_t
+nvmet_subsys_attr_serial_store_locked(struct nvmet_subsys *subsys,
+               const char *page, size_t count)
 {
-       struct nvmet_subsys *subsys = to_subsys(item);
        int pos, len = strcspn(page, "\n");
 
+       if (subsys->subsys_discovered) {
+               pr_err("Can't set serial number. %s is already assigned\n",
+                      subsys->serial);
+               return -EINVAL;
+       }
+
        if (!len || len > NVMET_SN_MAX_SIZE) {
                pr_err("Serial Number can not be empty or exceed %d Bytes\n",
                       NVMET_SN_MAX_SIZE);
@@ -1063,13 +1069,24 @@ static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
                }
        }
 
+       memcpy_and_pad(subsys->serial, NVMET_SN_MAX_SIZE, page, len, ' ');
+
+       return count;
+}
+
+static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
+                                             const char *page, size_t count)
+{
+       struct nvmet_subsys *subsys = to_subsys(item);
+       ssize_t ret;
+
        down_write(&nvmet_config_sem);
        mutex_lock(&subsys->lock);
-       memcpy_and_pad(subsys->serial, NVMET_SN_MAX_SIZE, page, len, ' ');
+       ret = nvmet_subsys_attr_serial_store_locked(subsys, page, count);
        mutex_unlock(&subsys->lock);
        up_write(&nvmet_config_sem);
 
-       return count;
+       return ret;
 }
 CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
 
index 0ae809c..bd0a0b9 100644 (file)
@@ -231,6 +231,7 @@ struct nvmet_subsys {
 
        u64                     ver;
        char                    serial[NVMET_SN_MAX_SIZE];
+       bool                    subsys_discovered;
        char                    *subsysnqn;
        bool                    pi_support;