* [PATCH v2 1/4] nvmet: change sn size and check validity
@ 2021-06-07 9:23 Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 2/4] nvmet: make sn stable once connection was established Max Gurtovoy
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Max Gurtovoy @ 2021-06-07 9:23 UTC (permalink / raw)
To: linux-nvme, sagi, kbusch, hch, chaitanya.kulkarni
Cc: ngottlieb, oren, Max Gurtovoy
From: Noam Gottlieb <ngottlieb@nvidia.com>
According to the NVM specification, the serial_number should be 20 bytes
(bytes 23:04 of the Identify Controller data structure), and should
contain only ASCII characters.
In accordance, the serial_number size is changed to 20 bytes and before
any attempt to store a new value in serial_number we check that the
input is valid - i.e. contains only ASCII characters, is not empty and
does not exceed 20 bytes.
Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Signed-off-by: Noam Gottlieb <ngottlieb@nvidia.com>
---
changes from v1: minor nits from Chaitanya
---
drivers/nvme/target/admin-cmd.c | 4 +---
drivers/nvme/target/configfs.c | 33 +++++++++++++++++++++++----------
drivers/nvme/target/core.c | 4 +++-
drivers/nvme/target/discovery.c | 4 +---
drivers/nvme/target/nvmet.h | 3 ++-
5 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index dcd49a72f2f3..9c73dbfb8228 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -357,9 +357,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->vid = 0;
id->ssvid = 0;
- memset(id->sn, ' ', sizeof(id->sn));
- bin2hex(id->sn, &ctrl->subsys->serial,
- min(sizeof(ctrl->subsys->serial), sizeof(id->sn) / 2));
+ memcpy(id->sn, ctrl->subsys->serial, NVMET_SN_MAX_SIZE);
memcpy_and_pad(id->mn, sizeof(id->mn), subsys->model_number,
strlen(subsys->model_number), ' ');
memcpy_and_pad(id->fr, sizeof(id->fr),
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 65a0cf99f557..027b28aaf7cd 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1030,24 +1030,43 @@ static ssize_t nvmet_subsys_attr_version_store(struct config_item *item,
}
CONFIGFS_ATTR(nvmet_subsys_, attr_version);
+/* See Section 1.5 of NVMe 1.4 */
+static bool nvmet_is_ascii(const char c)
+{
+ return c >= 0x20 && c <= 0x7e;
+}
+
static ssize_t nvmet_subsys_attr_serial_show(struct config_item *item,
char *page)
{
struct nvmet_subsys *subsys = to_subsys(item);
- return snprintf(page, PAGE_SIZE, "%llx\n", subsys->serial);
+ 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)
{
- u64 serial;
+ struct nvmet_subsys *subsys = to_subsys(item);
+ int pos, len = strcspn(page, "\n");
- if (sscanf(page, "%llx\n", &serial) != 1)
+ if (!len || len > NVMET_SN_MAX_SIZE) {
+ pr_err("Serial Number can not be empty or exceed %d Bytes\n",
+ NVMET_SN_MAX_SIZE);
return -EINVAL;
+ }
+
+ for (pos = 0; pos < len; pos++) {
+ if (!nvmet_is_ascii(page[pos])) {
+ pr_err("Serial Number must contain only ASCII strings\n");
+ return -EINVAL;
+ }
+ }
down_write(&nvmet_config_sem);
- to_subsys(item)->serial = serial;
+ mutex_lock(&subsys->lock);
+ memcpy_and_pad(subsys->serial, NVMET_SN_MAX_SIZE, page, len, ' ');
+ mutex_unlock(&subsys->lock);
up_write(&nvmet_config_sem);
return count;
@@ -1128,12 +1147,6 @@ static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
return ret;
}
-/* See Section 1.5 of NVMe 1.4 */
-static bool nvmet_is_ascii(const char c)
-{
- return c >= 0x20 && c <= 0x7e;
-}
-
static ssize_t nvmet_subsys_attr_model_store_locked(struct nvmet_subsys *subsys,
const char *page, size_t count)
{
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 4ae4bea6625d..213a0c2af4f7 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1493,6 +1493,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
enum nvme_subsys_type type)
{
struct nvmet_subsys *subsys;
+ char serial[NVMET_SN_MAX_SIZE / 2];
subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
if (!subsys)
@@ -1500,7 +1501,8 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
subsys->ver = NVMET_DEFAULT_VS;
/* generate a random serial number as our controllers are ephemeral: */
- get_random_bytes(&subsys->serial, sizeof(subsys->serial));
+ get_random_bytes(&serial, sizeof(serial));
+ bin2hex(subsys->serial, &serial, sizeof(serial));
switch (type) {
case NVME_NQN_NVME:
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index fc3645fc2c24..b7fdad13094a 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -262,9 +262,7 @@ static void nvmet_execute_disc_identify(struct nvmet_req *req)
goto out;
}
- memset(id->sn, ' ', sizeof(id->sn));
- bin2hex(id->sn, &ctrl->subsys->serial,
- min(sizeof(ctrl->subsys->serial), sizeof(id->sn) / 2));
+ memcpy(id->sn, ctrl->subsys->serial, NVMET_SN_MAX_SIZE);
memset(id->fr, ' ', sizeof(id->fr));
memcpy_and_pad(id->mn, sizeof(id->mn), model, sizeof(model) - 1, ' ');
memcpy_and_pad(id->fr, sizeof(id->fr),
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index d69a409515d6..0ae809ca428c 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -28,6 +28,7 @@
#define NVMET_NO_ERROR_LOC ((u16)-1)
#define NVMET_DEFAULT_CTRL_MODEL "Linux"
#define NVMET_MN_MAX_SIZE 40
+#define NVMET_SN_MAX_SIZE 20
/*
* Supported optional AENs:
@@ -229,7 +230,7 @@ struct nvmet_subsys {
u16 max_qid;
u64 ver;
- u64 serial;
+ char serial[NVMET_SN_MAX_SIZE];
char *subsysnqn;
bool pi_support;
--
2.25.1
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 2/4] nvmet: make sn stable once connection was established
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
@ 2021-06-07 9:23 ` Max Gurtovoy
2021-06-07 20:37 ` Chaitanya Kulkarni
2021-06-07 9:23 ` [PATCH v2 3/4] nvmet: allow mn change if subsys not discovered Max Gurtovoy
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Max Gurtovoy @ 2021-06-07 9:23 UTC (permalink / raw)
To: linux-nvme, sagi, kbusch, hch, chaitanya.kulkarni
Cc: ngottlieb, oren, Max Gurtovoy
From: Noam Gottlieb <ngottlieb@nvidia.com>
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>
---
drivers/nvme/target/admin-cmd.c | 6 ++++++
drivers/nvme/target/configfs.c | 27 ++++++++++++++++++++++-----
drivers/nvme/target/nvmet.h | 1 +
3 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 9c73dbfb8228..5f15c3285a5b 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -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.
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 027b28aaf7cd..a13da86fb374 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -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);
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 0ae809ca428c..bd0a0b91d843 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -231,6 +231,7 @@ struct nvmet_subsys {
u64 ver;
char serial[NVMET_SN_MAX_SIZE];
+ bool subsys_discovered;
char *subsysnqn;
bool pi_support;
--
2.25.1
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 2/4] nvmet: make sn stable once connection was established
2021-06-07 9:23 ` [PATCH v2 2/4] nvmet: make sn stable once connection was established Max Gurtovoy
@ 2021-06-07 20:37 ` Chaitanya Kulkarni
2021-06-08 11:36 ` Max Gurtovoy
0 siblings, 1 reply; 8+ messages in thread
From: Chaitanya Kulkarni @ 2021-06-07 20:37 UTC (permalink / raw)
To: Max Gurtovoy
Cc: linux-nvme@lists.infradead.org, sagi@grimberg.me,
kbusch@kernel.org, hch@lst.de, ngottlieb@nvidia.com,
oren@nvidia.com
Max,
On 6/7/21 02:23, Max Gurtovoy wrote:
> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
> index 0ae809ca428c..bd0a0b91d843 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -231,6 +231,7 @@ struct nvmet_subsys {
>
> u64 ver;
> char serial[NVMET_SN_MAX_SIZE];
> + bool subsys_discovered;
When subsystem is discovered (connected to the host) we will have non empty
controller list, instead of adding a new bool variable why not use
something like following tested patch on the top of this one ?
(that also fixes the indentation of
nvmet_subsys_attr_serial_store_locked()).
diff --git a/drivers/nvme/target/admin-cmd.c
b/drivers/nvme/target/admin-cmd.c
index bec84c231d37..897f419be618 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -366,12 +366,6 @@ 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.
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index a13da86fb374..94e23dca763f 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1046,11 +1046,11 @@ static ssize_t
nvmet_subsys_attr_serial_show(struct config_item *item,
static ssize_t
nvmet_subsys_attr_serial_store_locked(struct nvmet_subsys *subsys,
- const char *page, size_t count)
+ const char *page, size_t count)
{
int pos, len = strcspn(page, "\n");
- if (subsys->subsys_discovered) {
+ if (!list_empty(&subsys->ctrls)) {
pr_err("Can't set serial number. %s is already assigned\n",
subsys->serial);
return -EINVAL;
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index f7fbf9690ce8..73c6c4dc8997 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -232,7 +232,6 @@ struct nvmet_subsys {
u64 ver;
char serial[NVMET_SN_MAX_SIZE];
- bool subsys_discovered;
char *subsysnqn;
bool pi_support;
# nvme list
Node SN
Model Namespace
Usage Format FW Rev
--------------------- --------------------
---------------------------------------- ---------
-------------------------- ---------------- --------
/dev/nvme0n1 foo QEMU NVMe
Ctrl 1 1.07 GB / 1.07 GB
512 B + 0 B 1.0
/dev/nvme1n1 bf854da611a264d448c2
Linux 1 2.15 GB / 2.15
GB 4 KiB + 0 B 5.13.0-r
# echo 1 > /sys/kernel/config/nvmet/subsystems/nqn/
allowed_hosts/ attr_cntlid_min attr_serial passthru/
attr_allow_any_host attr_model attr_version
attr_cntlid_max attr_pi_enable namespaces/
# echo "1234567890" > /sys/kernel/config/nvmet/subsystems/nqn/attr_serial
bash: echo: write error: Invalid argument
# dmesg -c
[311081.155148] nvmet: Can't set serial number. bf854da611a264d448c2 is
already assigned
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 2/4] nvmet: make sn stable once connection was established
2021-06-07 20:37 ` Chaitanya Kulkarni
@ 2021-06-08 11:36 ` Max Gurtovoy
0 siblings, 0 replies; 8+ messages in thread
From: Max Gurtovoy @ 2021-06-08 11:36 UTC (permalink / raw)
To: Chaitanya Kulkarni
Cc: linux-nvme@lists.infradead.org, sagi@grimberg.me,
kbusch@kernel.org, hch@lst.de, ngottlieb@nvidia.com,
oren@nvidia.com
On 6/7/2021 11:37 PM, Chaitanya Kulkarni wrote:
> Max,
>
> On 6/7/21 02:23, Max Gurtovoy wrote:
>> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
>> index 0ae809ca428c..bd0a0b91d843 100644
>> --- a/drivers/nvme/target/nvmet.h
>> +++ b/drivers/nvme/target/nvmet.h
>> @@ -231,6 +231,7 @@ struct nvmet_subsys {
>>
>> u64 ver;
>> char serial[NVMET_SN_MAX_SIZE];
>> + bool subsys_discovered;
> When subsystem is discovered (connected to the host) we will have non empty
> controller list, instead of adding a new bool variable why not use
> something like following tested patch on the top of this one ?
No it's not the same. The controller list can be empty if initiator_A
performed connect + disconnect.
In your solution, it is allowed to change the sn after the disconnection
but in the original solution we don't allow this.
Once *any* initiator connected to this subsystem, the serial nmber will
not be changed anymore.
> (that also fixes the indentation of
> nvmet_subsys_attr_serial_store_locked()).
>
> diff --git a/drivers/nvme/target/admin-cmd.c
> b/drivers/nvme/target/admin-cmd.c
> index bec84c231d37..897f419be618 100644
> --- a/drivers/nvme/target/admin-cmd.c
> +++ b/drivers/nvme/target/admin-cmd.c
> @@ -366,12 +366,6 @@ 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.
> diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
> index a13da86fb374..94e23dca763f 100644
> --- a/drivers/nvme/target/configfs.c
> +++ b/drivers/nvme/target/configfs.c
> @@ -1046,11 +1046,11 @@ static ssize_t
> nvmet_subsys_attr_serial_show(struct config_item *item,
>
> static ssize_t
> nvmet_subsys_attr_serial_store_locked(struct nvmet_subsys *subsys,
> - const char *page, size_t count)
> + const char *page, size_t count)
> {
> int pos, len = strcspn(page, "\n");
>
> - if (subsys->subsys_discovered) {
> + if (!list_empty(&subsys->ctrls)) {
> pr_err("Can't set serial number. %s is already assigned\n",
> subsys->serial);
> return -EINVAL;
> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
> index f7fbf9690ce8..73c6c4dc8997 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -232,7 +232,6 @@ struct nvmet_subsys {
>
> u64 ver;
> char serial[NVMET_SN_MAX_SIZE];
> - bool subsys_discovered;
> char *subsysnqn;
> bool pi_support;
>
>
> # nvme list
> Node SN
> Model Namespace
> Usage Format FW Rev
> --------------------- --------------------
> ---------------------------------------- ---------
> -------------------------- ---------------- --------
> /dev/nvme0n1 foo QEMU NVMe
> Ctrl 1 1.07 GB / 1.07 GB
> 512 B + 0 B 1.0
> /dev/nvme1n1 bf854da611a264d448c2
> Linux 1 2.15 GB / 2.15
> GB 4 KiB + 0 B 5.13.0-r
> # echo 1 > /sys/kernel/config/nvmet/subsystems/nqn/
> allowed_hosts/ attr_cntlid_min attr_serial passthru/
> attr_allow_any_host attr_model attr_version
> attr_cntlid_max attr_pi_enable namespaces/
> # echo "1234567890" > /sys/kernel/config/nvmet/subsystems/nqn/attr_serial
> bash: echo: write error: Invalid argument
> # dmesg -c
> [311081.155148] nvmet: Can't set serial number. bf854da611a264d448c2 is
> already assigned
>
>
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] nvmet: allow mn change if subsys not discovered
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 2/4] nvmet: make sn stable once connection was established Max Gurtovoy
@ 2021-06-07 9:23 ` Max Gurtovoy
2021-06-07 9:23 ` [PATCH 4/4] nvmet: make ver stable once connection established Max Gurtovoy
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Max Gurtovoy @ 2021-06-07 9:23 UTC (permalink / raw)
To: linux-nvme, sagi, kbusch, hch, chaitanya.kulkarni
Cc: ngottlieb, oren, Max Gurtovoy
From: Noam Gottlieb <ngottlieb@nvidia.com>
Currently, once the subsystem's model_number is set for the first time
there is no way to change it. However, as long as no connection was
established to nvmf target, there is no reason for such restriction and
we should allow to change the subsystem's model_number as many times as
needed.
In addition, in order to simplfy the changes and make the model number
flow more similar to the rest of the attributes in the Identify
Controller data structure, we set a default value for the model number
at the initiation of the subsystem.
Reviewed-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Signed-off-by: Noam Gottlieb <ngottlieb@nvidia.com>
---
drivers/nvme/target/admin-cmd.c | 26 --------------------------
drivers/nvme/target/configfs.c | 10 ++--------
drivers/nvme/target/core.c | 21 +++++++++++++++++----
drivers/nvme/target/discovery.c | 4 ++--
4 files changed, 21 insertions(+), 40 deletions(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 5f15c3285a5b..cd60a8184d04 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -313,22 +313,6 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req)
nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_SC_DNR);
}
-static u16 nvmet_set_model_number(struct nvmet_subsys *subsys)
-{
- u16 status = 0;
-
- mutex_lock(&subsys->lock);
- if (!subsys->model_number) {
- subsys->model_number =
- kstrdup(NVMET_DEFAULT_CTRL_MODEL, GFP_KERNEL);
- if (!subsys->model_number)
- status = NVME_SC_INTERNAL;
- }
- mutex_unlock(&subsys->lock);
-
- return status;
-}
-
static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -343,16 +327,6 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
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.
- */
- if (!subsys->model_number) {
- status = nvmet_set_model_number(subsys);
- if (status)
- goto out;
- }
-
id = kzalloc(sizeof(*id), GFP_KERNEL);
if (!id) {
status = NVME_SC_INTERNAL;
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index a13da86fb374..9ef8708b92c6 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1154,14 +1154,8 @@ static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
char *page)
{
struct nvmet_subsys *subsys = to_subsys(item);
- int ret;
-
- mutex_lock(&subsys->lock);
- ret = snprintf(page, PAGE_SIZE, "%s\n", subsys->model_number ?
- subsys->model_number : NVMET_DEFAULT_CTRL_MODEL);
- mutex_unlock(&subsys->lock);
- return ret;
+ return snprintf(page, PAGE_SIZE, "%s\n", subsys->model_number);
}
static ssize_t nvmet_subsys_attr_model_store_locked(struct nvmet_subsys *subsys,
@@ -1169,7 +1163,7 @@ static ssize_t nvmet_subsys_attr_model_store_locked(struct nvmet_subsys *subsys,
{
int pos = 0, len;
- if (subsys->model_number) {
+ if (subsys->subsys_discovered) {
pr_err("Can't set model number. %s is already assigned\n",
subsys->model_number);
return -EINVAL;
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 213a0c2af4f7..146909486b8f 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1494,6 +1494,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
{
struct nvmet_subsys *subsys;
char serial[NVMET_SN_MAX_SIZE / 2];
+ int ret;
subsys = kzalloc(sizeof(*subsys), GFP_KERNEL);
if (!subsys)
@@ -1504,6 +1505,12 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
get_random_bytes(&serial, sizeof(serial));
bin2hex(subsys->serial, &serial, sizeof(serial));
+ subsys->model_number = kstrdup(NVMET_DEFAULT_CTRL_MODEL, GFP_KERNEL);
+ if (!subsys->model_number) {
+ ret = -ENOMEM;
+ goto free_subsys;
+ }
+
switch (type) {
case NVME_NQN_NVME:
subsys->max_qid = NVMET_NR_QUEUES;
@@ -1513,15 +1520,15 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
break;
default:
pr_err("%s: Unknown Subsystem type - %d\n", __func__, type);
- kfree(subsys);
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto free_mn;
}
subsys->type = type;
subsys->subsysnqn = kstrndup(subsysnqn, NVMF_NQN_SIZE,
GFP_KERNEL);
if (!subsys->subsysnqn) {
- kfree(subsys);
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto free_mn;
}
subsys->cntlid_min = NVME_CNTLID_MIN;
subsys->cntlid_max = NVME_CNTLID_MAX;
@@ -1533,6 +1540,12 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
INIT_LIST_HEAD(&subsys->hosts);
return subsys;
+
+free_mn:
+ kfree(subsys->model_number);
+free_subsys:
+ kfree(subsys);
+ return ERR_PTR(ret);
}
static void nvmet_subsys_free(struct kref *ref)
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index b7fdad13094a..7aa62bc6ae84 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -244,7 +244,6 @@ static void nvmet_execute_disc_identify(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
struct nvme_id_ctrl *id;
- const char model[] = "Linux";
u16 status = 0;
if (!nvmet_check_transfer_len(req, NVME_IDENTIFY_DATA_SIZE))
@@ -264,7 +263,8 @@ static void nvmet_execute_disc_identify(struct nvmet_req *req)
memcpy(id->sn, ctrl->subsys->serial, NVMET_SN_MAX_SIZE);
memset(id->fr, ' ', sizeof(id->fr));
- memcpy_and_pad(id->mn, sizeof(id->mn), model, sizeof(model) - 1, ' ');
+ memcpy_and_pad(id->mn, sizeof(id->mn), ctrl->subsys->model_number,
+ strlen(ctrl->subsys->model_number), ' ');
memcpy_and_pad(id->fr, sizeof(id->fr),
UTS_RELEASE, strlen(UTS_RELEASE), ' ');
--
2.25.1
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/4] nvmet: make ver stable once connection established
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 2/4] nvmet: make sn stable once connection was established Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 3/4] nvmet: allow mn change if subsys not discovered Max Gurtovoy
@ 2021-06-07 9:23 ` Max Gurtovoy
2021-06-07 19:59 ` [PATCH v2 1/4] nvmet: change sn size and check validity Chaitanya Kulkarni
2021-06-08 16:44 ` Christoph Hellwig
4 siblings, 0 replies; 8+ messages in thread
From: Max Gurtovoy @ 2021-06-07 9:23 UTC (permalink / raw)
To: linux-nvme, sagi, kbusch, hch, chaitanya.kulkarni
Cc: ngottlieb, oren, Max Gurtovoy
From: Noam Gottlieb <ngottlieb@nvidia.com>
Once some host has connected to the nvmf target, make sure that the
version number is stable and cannot be changed.
Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Signed-off-by: Noam Gottlieb <ngottlieb@nvidia.com>
---
changes from v1: changing "ret" to ssize_t (from Chaitanya)
---
drivers/nvme/target/configfs.c | 36 +++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 9ef8708b92c6..273555127188 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1007,13 +1007,26 @@ static ssize_t nvmet_subsys_attr_version_show(struct config_item *item,
NVME_MINOR(subsys->ver));
}
-static ssize_t nvmet_subsys_attr_version_store(struct config_item *item,
- const char *page, size_t count)
+static ssize_t
+nvmet_subsys_attr_version_store_locked(struct nvmet_subsys *subsys,
+ const char *page, size_t count)
{
- struct nvmet_subsys *subsys = to_subsys(item);
int major, minor, tertiary = 0;
int ret;
+ if (subsys->subsys_discovered) {
+ if (NVME_TERTIARY(subsys->ver))
+ pr_err("Can't set version number. %llu.%llu.%llu is already assigned\n",
+ NVME_MAJOR(subsys->ver),
+ NVME_MINOR(subsys->ver),
+ NVME_TERTIARY(subsys->ver));
+ else
+ pr_err("Can't set version number. %llu.%llu is already assigned\n",
+ NVME_MAJOR(subsys->ver),
+ NVME_MINOR(subsys->ver));
+ return -EINVAL;
+ }
+
/* passthru subsystems use the underlying controller's version */
if (nvmet_passthru_ctrl(subsys))
return -EINVAL;
@@ -1022,12 +1035,25 @@ static ssize_t nvmet_subsys_attr_version_store(struct config_item *item,
if (ret != 2 && ret != 3)
return -EINVAL;
- down_write(&nvmet_config_sem);
subsys->ver = NVME_VS(major, minor, tertiary);
- up_write(&nvmet_config_sem);
return count;
}
+
+static ssize_t nvmet_subsys_attr_version_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);
+ ret = nvmet_subsys_attr_version_store_locked(subsys, page, count);
+ mutex_unlock(&subsys->lock);
+ up_write(&nvmet_config_sem);
+
+ return ret;
+}
CONFIGFS_ATTR(nvmet_subsys_, attr_version);
/* See Section 1.5 of NVMe 1.4 */
--
2.25.1
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] nvmet: change sn size and check validity
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
` (2 preceding siblings ...)
2021-06-07 9:23 ` [PATCH 4/4] nvmet: make ver stable once connection established Max Gurtovoy
@ 2021-06-07 19:59 ` Chaitanya Kulkarni
2021-06-08 16:44 ` Christoph Hellwig
4 siblings, 0 replies; 8+ messages in thread
From: Chaitanya Kulkarni @ 2021-06-07 19:59 UTC (permalink / raw)
To: Max Gurtovoy, linux-nvme@lists.infradead.org, sagi@grimberg.me,
kbusch@kernel.org, hch@lst.de
Cc: ngottlieb@nvidia.com, oren@nvidia.com
On 6/7/21 02:23, Max Gurtovoy wrote:
> From: Noam Gottlieb <ngottlieb@nvidia.com>
>
> According to the NVM specification, the serial_number should be 20 bytes
> (bytes 23:04 of the Identify Controller data structure), and should
> contain only ASCII characters.
>
> In accordance, the serial_number size is changed to 20 bytes and before
> any attempt to store a new value in serial_number we check that the
> input is valid - i.e. contains only ASCII characters, is not empty and
> does not exceed 20 bytes.
>
> Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com>
> Signed-off-by: Noam Gottlieb <ngottlieb@nvidia.com>
> ---
Looks good.
Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] nvmet: change sn size and check validity
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
` (3 preceding siblings ...)
2021-06-07 19:59 ` [PATCH v2 1/4] nvmet: change sn size and check validity Chaitanya Kulkarni
@ 2021-06-08 16:44 ` Christoph Hellwig
4 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2021-06-08 16:44 UTC (permalink / raw)
To: Max Gurtovoy
Cc: linux-nvme, sagi, kbusch, hch, chaitanya.kulkarni, ngottlieb,
oren
Thanks,
applied to nvme-5.14.
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-06-08 16:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-07 9:23 [PATCH v2 1/4] nvmet: change sn size and check validity Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 2/4] nvmet: make sn stable once connection was established Max Gurtovoy
2021-06-07 20:37 ` Chaitanya Kulkarni
2021-06-08 11:36 ` Max Gurtovoy
2021-06-07 9:23 ` [PATCH v2 3/4] nvmet: allow mn change if subsys not discovered Max Gurtovoy
2021-06-07 9:23 ` [PATCH 4/4] nvmet: make ver stable once connection established Max Gurtovoy
2021-06-07 19:59 ` [PATCH v2 1/4] nvmet: change sn size and check validity Chaitanya Kulkarni
2021-06-08 16:44 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox