mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 10:19:47 +00:00
nvmet: make ctrl-id configurable
This patch adds a new target subsys attribute which allows user to optionally specify target controller IDs which then used in the nvmet_execute_identify_ctrl() to fill up the nvme_id_ctrl structure. For example, when using a cluster setup with two nodes, with a dual ported NVMe drive and exporting the drive from both the nodes, The connection to the host fails due to the same controller ID and results in the following error message:- "nvme nvmeX: Duplicate cntlid XXX with nvmeX, rejecting" With this patch now user can partition the controller IDs for each subsystem by setting up the cntlid_min and cntlid_max. These values will be used at the time of the controller ID creation. By partitioning the ctrl-ids for each subsystem results in the unique ctrl-id space which avoids the collision. When new attribute is not specified target will fall back to original cntlid calculation method. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
parent
527123c7de
commit
94a39d61f8
3 changed files with 70 additions and 2 deletions
|
@ -859,10 +859,72 @@ static ssize_t nvmet_subsys_attr_serial_store(struct config_item *item,
|
|||
}
|
||||
CONFIGFS_ATTR(nvmet_subsys_, attr_serial);
|
||||
|
||||
static ssize_t nvmet_subsys_attr_cntlid_min_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cntlid_min);
|
||||
}
|
||||
|
||||
static ssize_t nvmet_subsys_attr_cntlid_min_store(struct config_item *item,
|
||||
const char *page, size_t cnt)
|
||||
{
|
||||
u16 cntlid_min;
|
||||
|
||||
if (sscanf(page, "%hu\n", &cntlid_min) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (cntlid_min == 0)
|
||||
return -EINVAL;
|
||||
|
||||
down_write(&nvmet_config_sem);
|
||||
if (cntlid_min >= to_subsys(item)->cntlid_max)
|
||||
goto out_unlock;
|
||||
to_subsys(item)->cntlid_min = cntlid_min;
|
||||
up_write(&nvmet_config_sem);
|
||||
return cnt;
|
||||
|
||||
out_unlock:
|
||||
up_write(&nvmet_config_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
CONFIGFS_ATTR(nvmet_subsys_, attr_cntlid_min);
|
||||
|
||||
static ssize_t nvmet_subsys_attr_cntlid_max_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%u\n", to_subsys(item)->cntlid_max);
|
||||
}
|
||||
|
||||
static ssize_t nvmet_subsys_attr_cntlid_max_store(struct config_item *item,
|
||||
const char *page, size_t cnt)
|
||||
{
|
||||
u16 cntlid_max;
|
||||
|
||||
if (sscanf(page, "%hu\n", &cntlid_max) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (cntlid_max == 0)
|
||||
return -EINVAL;
|
||||
|
||||
down_write(&nvmet_config_sem);
|
||||
if (cntlid_max <= to_subsys(item)->cntlid_min)
|
||||
goto out_unlock;
|
||||
to_subsys(item)->cntlid_max = cntlid_max;
|
||||
up_write(&nvmet_config_sem);
|
||||
return cnt;
|
||||
|
||||
out_unlock:
|
||||
up_write(&nvmet_config_sem);
|
||||
return -EINVAL;
|
||||
}
|
||||
CONFIGFS_ATTR(nvmet_subsys_, attr_cntlid_max);
|
||||
|
||||
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_cntlid_min,
|
||||
&nvmet_subsys_attr_attr_cntlid_max,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -1289,8 +1289,11 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
|
|||
if (!ctrl->sqs)
|
||||
goto out_free_cqs;
|
||||
|
||||
if (subsys->cntlid_min > subsys->cntlid_max)
|
||||
goto out_free_cqs;
|
||||
|
||||
ret = ida_simple_get(&cntlid_ida,
|
||||
NVME_CNTLID_MIN, NVME_CNTLID_MAX,
|
||||
subsys->cntlid_min, subsys->cntlid_max,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
status = NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR;
|
||||
|
@ -1438,7 +1441,8 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
|
|||
kfree(subsys);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
subsys->cntlid_min = NVME_CNTLID_MIN;
|
||||
subsys->cntlid_max = NVME_CNTLID_MAX;
|
||||
kref_init(&subsys->ref);
|
||||
|
||||
mutex_init(&subsys->lock);
|
||||
|
|
|
@ -211,6 +211,8 @@ struct nvmet_subsys {
|
|||
struct list_head namespaces;
|
||||
unsigned int nr_namespaces;
|
||||
unsigned int max_nsid;
|
||||
u16 cntlid_min;
|
||||
u16 cntlid_max;
|
||||
|
||||
struct list_head ctrls;
|
||||
|
||||
|
|
Loading…
Reference in a new issue