* A patch for review that allows dynamic configuration of the subsystem model.
@ 2019-10-30 12:43 Mark Ruijter
0 siblings, 0 replies; only message in thread
From: Mark Ruijter @ 2019-10-30 12:43 UTC (permalink / raw)
To: Keith Busch; +Cc: linux-nvme
[-- Attachment #1: Type: text/plain, Size: 1415 bytes --]
The attached patch allows to dynamically change the subsystem model while keeping 'Linux' as the default.
For example:
dev:/sys/kernel/config/nvmet/subsystems/loop # cat attr_model
Linux
# nvme list
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 4d11eb57c7078f19 Linux 1 104,86 MB / 104,86 MB 512 B + 0 B 5.3.5
# echo mypool/myvolume > attr_model
root@crunchie:/tmp# nvme list
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 4d11eb57c7078f19 mypool/myvolume 1 104,86 MB / 104,86 MB 512 B + 0 B 5.3.5
The attr_model input is validated to what the NVME specification allows for a ascii string:
echo -e "my\t pool" > attr_model
-bash: echo: write error: Invalid argument
dev:/sys/kernel/config/nvmet/subsystems/loop #
I hope this is useful,
Thanks,
Mark Ruijter
[-- Attachment #2: subsystem_model.patch --]
[-- Type: application/octet-stream, Size: 3477 bytes --]
diff --git a/admin-cmd.c b/admin-cmd.c
index 51800a9..bbf6fec 100644
--- a/admin-cmd.c
+++ b/admin-cmd.c
@@ -289,7 +289,6 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
struct nvmet_ctrl *ctrl = req->sq->ctrl;
struct nvme_id_ctrl *id;
u16 status = 0;
- const char model[] = "Linux";
id = kzalloc(sizeof(*id), GFP_KERNEL);
if (!id) {
@@ -304,7 +303,8 @@ 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));
- memcpy_and_pad(id->mn, sizeof(id->mn), model, sizeof(model) - 1, ' ');
+ memcpy_and_pad(id->mn, sizeof(id->mn), ctrl->subsys->model,
+ strlen(ctrl->subsys->model), ' ');
memcpy_and_pad(id->fr, sizeof(id->fr),
UTS_RELEASE, strlen(UTS_RELEASE), ' ');
diff --git a/configfs.c b/configfs.c
index 59c2b79..123289d 100644
--- a/configfs.c
+++ b/configfs.c
@@ -891,10 +891,56 @@ static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
}
CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
+static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
+ char *page)
+{
+ struct nvmet_subsys *subsys = to_subsys(item);
+
+ return snprintf(page, PAGE_SIZE, "%s\n", subsys->model);
+}
+
+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);
+ int len;
+ int ret = -EINVAL;
+ char c;
+ int pos = 0;
+
+ down_write(&nvmet_config_sem);
+ len = strcspn(page, "\n");
+ if (!len)
+ goto out_unlock;
+
+ /* Only 20h until 7eh is allowed */
+ c = page[pos];
+ while (pos < len)
+ {
+ if (c < 0x20 || c > 0x7e) {
+ goto out_unlock;
+ }
+ pos++;
+ c = page[pos];
+ }
+
+ kfree(subsys->model);
+ ret = -ENOMEM;
+ subsys->model = kstrndup(page, len, GFP_KERNEL);
+ if(subsys->model)
+ ret = count;
+out_unlock:
+ up_write(&nvmet_config_sem);
+ return ret;
+}
+
+CONFIGFS_ATTR(nvmet_subsys_, attr_model);
+
static struct configfs_attribute *nvmet_subsys_attrs[] = {
&nvmet_subsys_attr_attr_allow_any_host,
&nvmet_subsys_attr_attr_version,
&nvmet_subsys_attr_attr_serial,
+ &nvmet_subsys_attr_attr_model,
NULL,
};
@@ -930,6 +976,7 @@ static struct config_group *nvmet_subsys_make(struct config_group *group,
}
subsys = nvmet_subsys_alloc(name, NVME_NQN_NVME);
+ subsys->model = kstrdup("Linux", GFP_KERNEL);
if (IS_ERR(subsys))
return ERR_CAST(subsys);
diff --git a/core.c b/core.c
index 9f17d07..6049e6a 100644
--- a/core.c
+++ b/core.c
@@ -1418,6 +1418,12 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
kfree(subsys);
return ERR_PTR(-ENOMEM);
}
+ subsys->model = kstrdup("Linux", GFP_KERNEL);
+ if (!subsys->model) {
+ kfree(subsys->subsysnqn);
+ kfree(subsys);
+ return ERR_PTR(-ENOMEM);
+ }
kref_init(&subsys->ref);
@@ -1437,6 +1443,7 @@ static void nvmet_subsys_free(struct kref *ref)
WARN_ON_ONCE(!list_empty(&subsys->namespaces));
kfree(subsys->subsysnqn);
+ kfree(subsys->model);
kfree(subsys);
}
diff --git a/nvmet.h b/nvmet.h
index 20aa830..200c03c 100644
--- a/nvmet.h
+++ b/nvmet.h
@@ -223,6 +223,7 @@ struct nvmet_subsys {
u64 ver;
u64 serial;
char *subsysnqn;
+ char *model;
struct config_group group;
[-- Attachment #3: Type: text/plain, Size: 158 bytes --]
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2019-10-30 12:43 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-30 12:43 A patch for review that allows dynamic configuration of the subsystem model Mark Ruijter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).