Skip to content

Commit 013b7eb

Browse files
markruijterkeithbusch
authored andcommitted
nvmet: make ctrl model configurable
This patch adds a new target subsys attribute which allows user to optionally specify model name which then used in the nvmet_execute_identify_ctrl() to fill up the nvme_id_ctrl structure. The default value for the model is set to "Linux" for backward compatibility. Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Mark Ruijter <MRuijter@onestopsystems.com> [chaitanya.kulkarni@wdc.com *Use macro for default model, coding style fixes. *Use RCU for accessing model in for configfs and in nvmet_execute_identify_ctrl(). ] Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent 94a39d6 commit 013b7eb

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

drivers/nvme/target/admin-cmd.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,25 @@ static void nvmet_execute_get_log_page(struct nvmet_req *req)
322322
nvmet_req_complete(req, NVME_SC_INVALID_FIELD | NVME_SC_DNR);
323323
}
324324

325+
static void nvmet_id_set_model_number(struct nvme_id_ctrl *id,
326+
struct nvmet_subsys *subsys)
327+
{
328+
const char *model = NVMET_DEFAULT_CTRL_MODEL;
329+
struct nvmet_subsys_model *subsys_model;
330+
331+
rcu_read_lock();
332+
subsys_model = rcu_dereference(subsys->model);
333+
if (subsys_model)
334+
model = subsys_model->number;
335+
memcpy_and_pad(id->mn, sizeof(id->mn), model, strlen(model), ' ');
336+
rcu_read_unlock();
337+
}
338+
325339
static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
326340
{
327341
struct nvmet_ctrl *ctrl = req->sq->ctrl;
328342
struct nvme_id_ctrl *id;
329343
u16 status = 0;
330-
const char model[] = "Linux";
331344

332345
id = kzalloc(sizeof(*id), GFP_KERNEL);
333346
if (!id) {
@@ -342,7 +355,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
342355
memset(id->sn, ' ', sizeof(id->sn));
343356
bin2hex(id->sn, &ctrl->subsys->serial,
344357
min(sizeof(ctrl->subsys->serial), sizeof(id->sn) / 2));
345-
memcpy_and_pad(id->mn, sizeof(id->mn), model, sizeof(model) - 1, ' ');
358+
nvmet_id_set_model_number(id, ctrl->subsys);
346359
memcpy_and_pad(id->fr, sizeof(id->fr),
347360
UTS_RELEASE, strlen(UTS_RELEASE), ' ');
348361

drivers/nvme/target/configfs.c

+66
Original file line numberDiff line numberDiff line change
@@ -919,12 +919,78 @@ static ssize_t nvmet_subsys_attr_cntlid_max_store(struct config_item *item,
919919
}
920920
CONFIGFS_ATTR(nvmet_subsys_, attr_cntlid_max);
921921

922+
static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
923+
char *page)
924+
{
925+
struct nvmet_subsys *subsys = to_subsys(item);
926+
struct nvmet_subsys_model *subsys_model;
927+
char *model = NVMET_DEFAULT_CTRL_MODEL;
928+
int ret;
929+
930+
rcu_read_lock();
931+
subsys_model = rcu_dereference(subsys->model);
932+
if (subsys_model)
933+
model = subsys_model->number;
934+
ret = snprintf(page, PAGE_SIZE, "%s\n", model);
935+
rcu_read_unlock();
936+
937+
return ret;
938+
}
939+
940+
/* See Section 1.5 of NVMe 1.4 */
941+
static bool nvmet_is_ascii(const char c)
942+
{
943+
return c >= 0x20 && c <= 0x7e;
944+
}
945+
946+
static ssize_t nvmet_subsys_attr_model_store(struct config_item *item,
947+
const char *page, size_t count)
948+
{
949+
struct nvmet_subsys *subsys = to_subsys(item);
950+
struct nvmet_subsys_model *new_model;
951+
char *new_model_number;
952+
int pos = 0, len;
953+
954+
len = strcspn(page, "\n");
955+
if (!len)
956+
return -EINVAL;
957+
958+
for (pos = 0; pos < len; pos++) {
959+
if (!nvmet_is_ascii(page[pos]))
960+
return -EINVAL;
961+
}
962+
963+
new_model_number = kstrndup(page, len, GFP_KERNEL);
964+
if (!new_model_number)
965+
return -ENOMEM;
966+
967+
new_model = kzalloc(sizeof(*new_model) + len + 1, GFP_KERNEL);
968+
if (!new_model) {
969+
kfree(new_model_number);
970+
return -ENOMEM;
971+
}
972+
memcpy(new_model->number, new_model_number, len);
973+
974+
down_write(&nvmet_config_sem);
975+
mutex_lock(&subsys->lock);
976+
new_model = rcu_replace_pointer(subsys->model, new_model,
977+
mutex_is_locked(&subsys->lock));
978+
mutex_unlock(&subsys->lock);
979+
up_write(&nvmet_config_sem);
980+
981+
kfree_rcu(new_model, rcuhead);
982+
983+
return count;
984+
}
985+
CONFIGFS_ATTR(nvmet_subsys_, attr_model);
986+
922987
static struct configfs_attribute *nvmet_subsys_attrs[] = {
923988
&nvmet_subsys_attr_attr_allow_any_host,
924989
&nvmet_subsys_attr_attr_version,
925990
&nvmet_subsys_attr_attr_serial,
926991
&nvmet_subsys_attr_attr_cntlid_min,
927992
&nvmet_subsys_attr_attr_cntlid_max,
993+
&nvmet_subsys_attr_attr_model,
928994
NULL,
929995
};
930996

drivers/nvme/target/core.c

+1
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,7 @@ static void nvmet_subsys_free(struct kref *ref)
14611461
WARN_ON_ONCE(!list_empty(&subsys->namespaces));
14621462

14631463
kfree(subsys->subsysnqn);
1464+
kfree_rcu(subsys->model, rcuhead);
14641465
kfree(subsys);
14651466
}
14661467

drivers/nvme/target/nvmet.h

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define NVMET_ASYNC_EVENTS 4
2424
#define NVMET_ERROR_LOG_SLOTS 128
2525
#define NVMET_NO_ERROR_LOC ((u16)-1)
26+
#define NVMET_DEFAULT_CTRL_MODEL "Linux"
2627

2728
/*
2829
* Supported optional AENs:
@@ -202,6 +203,11 @@ struct nvmet_ctrl {
202203
struct nvme_error_slot slots[NVMET_ERROR_LOG_SLOTS];
203204
};
204205

206+
struct nvmet_subsys_model {
207+
struct rcu_head rcuhead;
208+
char number[];
209+
};
210+
205211
struct nvmet_subsys {
206212
enum nvme_subsys_type type;
207213

@@ -229,6 +235,8 @@ struct nvmet_subsys {
229235

230236
struct config_group namespaces_group;
231237
struct config_group allowed_hosts_group;
238+
239+
struct nvmet_subsys_model __rcu *model;
232240
};
233241

234242
static inline struct nvmet_subsys *to_subsys(struct config_item *item)

0 commit comments

Comments
 (0)