From: Max Gurtovoy <mgurtovoy@nvidia.com>
To: <linux-nvme@lists.infradead.org>, <sagi@grimberg.me>,
<kbusch@kernel.org>, <hch@lst.de>, <chaitanya.kulkarni@wdc.com>
Cc: Max Gurtovoy <mgurtovoy@nvidia.com>, oren@nvidia.com
Subject: [PATCH 1/1] nvmet: allow setting model_number once
Date: Wed, 17 Feb 2021 18:11:53 +0000 [thread overview]
Message-ID: <20210217181153.15343-1-mgurtovoy@nvidia.com> (raw)
In case we have already established connection to nvmf target, it
shouldn't be allowed to change the model_number. E.g. if someone will
identify ctrl and get model_number of "my_model" later on will change
the model_numbel via configfs to "my_new_model" this will break the NVM
specification for "Get Log Page – Persistent Event Log" that refers to
Model Number as: "This field contains the same value as reported in the
Model Number field of the Identify Controller data structure, bytes
63:24."
Although it doesn't mentioned explicitly that this field can't be
changed, we can assume it.
So allow setting this field only once: using configfs or in the first
identify ctrl operation.
Signed-off-by: Max Gurtovoy <mgurtovoy@nvidia.com>
---
drivers/nvme/target/admin-cmd.c | 33 +++++++++++++------
drivers/nvme/target/configfs.c | 57 ++++++++++++++++++---------------
drivers/nvme/target/core.c | 2 +-
drivers/nvme/target/nvmet.h | 7 +---
4 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index dc1ea468b182..6a3341b2091f 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -319,18 +319,25 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req)
nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_SC_DNR);
}
-static void nvmet_id_set_model_number(struct nvme_id_ctrl *id,
+static int nvmet_id_set_model_number(struct nvme_id_ctrl *id,
struct nvmet_subsys *subsys)
{
- const char *model = NVMET_DEFAULT_CTRL_MODEL;
- struct nvmet_subsys_model *subsys_model;
+ int ret = 0;
- rcu_read_lock();
- subsys_model = rcu_dereference(subsys->model);
- if (subsys_model)
- model = subsys_model->number;
- memcpy_and_pad(id->mn, sizeof(id->mn), model, strlen(model), ' ');
- rcu_read_unlock();
+ mutex_lock(&subsys->lock);
+ if (!subsys->model_number) {
+ subsys->model_number = kstrdup(NVMET_DEFAULT_CTRL_MODEL,
+ GFP_KERNEL);
+ if (!subsys->model_number) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+ }
+ memcpy_and_pad(id->mn, sizeof(id->mn), subsys->model_number,
+ strlen(subsys->model_number), ' ');
+out_unlock:
+ mutex_unlock(&subsys->lock);
+ return ret;
}
static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
@@ -339,6 +346,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
struct nvme_id_ctrl *id;
u32 cmd_capsule_size;
u16 status = 0;
+ int ret;
id = kzalloc(sizeof(*id), GFP_KERNEL);
if (!id) {
@@ -353,7 +361,11 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
memset(id->sn, ' ', sizeof(id->sn));
bin2hex(id->sn, &ctrl->subsys->serial,
min(sizeof(ctrl->subsys->serial), sizeof(id->sn) / 2));
- nvmet_id_set_model_number(id, ctrl->subsys);
+ ret = nvmet_id_set_model_number(id, ctrl->subsys);
+ if (ret) {
+ status = NVME_SC_INTERNAL;
+ goto out_free;
+ }
memcpy_and_pad(id->fr, sizeof(id->fr),
UTS_RELEASE, strlen(UTS_RELEASE), ' ');
@@ -461,6 +473,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
+out_free:
kfree(id);
out:
nvmet_req_complete(req, status);
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index c61ffd767062..ad1adcf30ee5 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1120,16 +1120,14 @@ static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
char *page)
{
struct nvmet_subsys *subsys = to_subsys(item);
- struct nvmet_subsys_model *subsys_model;
- char *model = NVMET_DEFAULT_CTRL_MODEL;
+ char *model = "";
int ret;
- rcu_read_lock();
- subsys_model = rcu_dereference(subsys->model);
- if (subsys_model)
- model = subsys_model->number;
+ mutex_lock(&subsys->lock);
+ if (subsys->model_number)
+ model = subsys->model_number;
ret = snprintf(page, PAGE_SIZE, "%s\n", model);
- rcu_read_unlock();
+ mutex_unlock(&subsys->lock);
return ret;
}
@@ -1144,40 +1142,49 @@ static ssize_t nvmet_subsys_attr_model_store(struct config_item *item,
const char *page, size_t count)
{
struct nvmet_subsys *subsys = to_subsys(item);
- struct nvmet_subsys_model *new_model;
char *new_model_number;
int pos = 0, len;
+ down_write(&nvmet_config_sem);
+ mutex_lock(&subsys->lock);
+ if (subsys->model_number) {
+ pr_err("Can't set model number. %s is already assigned\n",
+ subsys->model_number);
+ count = -EINVAL;
+ goto out_unlock;
+ }
+
len = strcspn(page, "\n");
- if (!len)
- return -EINVAL;
+ if (!len) {
+ count = -EINVAL;
+ goto out_unlock;
+ }
for (pos = 0; pos < len; pos++) {
- if (!nvmet_is_ascii(page[pos]))
- return -EINVAL;
+ if (!nvmet_is_ascii(page[pos])) {
+ count = -EINVAL;
+ goto out_unlock;
+ }
}
new_model_number = kmemdup_nul(page, len, GFP_KERNEL);
- if (!new_model_number)
- return -ENOMEM;
+ if (!new_model_number) {
+ count = -ENOMEM;
+ goto out_unlock;
+ }
- new_model = kzalloc(sizeof(*new_model) + len + 1, GFP_KERNEL);
- if (!new_model) {
+ subsys->model_number = kstrdup(new_model_number, GFP_KERNEL);
+ if (!subsys->model_number) {
+ count = -ENOMEM;
kfree(new_model_number);
- return -ENOMEM;
+ goto out_unlock;
}
- memcpy(new_model->number, new_model_number, len);
- down_write(&nvmet_config_sem);
- mutex_lock(&subsys->lock);
- new_model = rcu_replace_pointer(subsys->model, new_model,
- mutex_is_locked(&subsys->lock));
+ kfree(new_model_number);
+out_unlock:
mutex_unlock(&subsys->lock);
up_write(&nvmet_config_sem);
- kfree_rcu(new_model, rcuhead);
- kfree(new_model_number);
-
return count;
}
CONFIGFS_ATTR(nvmet_subsys_, attr_model);
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 8ce4d59cc9e7..c7af907912f2 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -1521,7 +1521,7 @@ static void nvmet_subsys_free(struct kref *ref)
nvmet_passthru_subsys_free(subsys);
kfree(subsys->subsysnqn);
- kfree_rcu(subsys->model, rcuhead);
+ kfree(subsys->model_number);
kfree(subsys);
}
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 592763732065..aac741bf378c 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -208,11 +208,6 @@ struct nvmet_ctrl {
bool pi_support;
};
-struct nvmet_subsys_model {
- struct rcu_head rcuhead;
- char number[];
-};
-
struct nvmet_subsys {
enum nvme_subsys_type type;
@@ -242,7 +237,7 @@ struct nvmet_subsys {
struct config_group namespaces_group;
struct config_group allowed_hosts_group;
- struct nvmet_subsys_model __rcu *model;
+ char *model_number;
#ifdef CONFIG_NVME_TARGET_PASSTHRU
struct nvme_ctrl *passthru_ctrl;
--
2.25.4
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
next reply other threads:[~2021-02-17 18:12 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-17 18:11 Max Gurtovoy [this message]
2021-02-18 3:17 ` [PATCH 1/1] nvmet: allow setting model_number once Chaitanya Kulkarni
2021-02-18 9:51 ` Max Gurtovoy
2021-02-24 9:43 ` Christoph Hellwig
2021-02-24 9:59 ` Max Gurtovoy
2021-02-24 10:00 ` Christoph Hellwig
2021-02-24 10:02 ` Max Gurtovoy
2021-02-24 10:04 ` Christoph Hellwig
2021-02-24 12:57 ` Max Gurtovoy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210217181153.15343-1-mgurtovoy@nvidia.com \
--to=mgurtovoy@nvidia.com \
--cc=chaitanya.kulkarni@wdc.com \
--cc=hch@lst.de \
--cc=kbusch@kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=oren@nvidia.com \
--cc=sagi@grimberg.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox