[PATCH] nvmet: parametrize maximum number of namespaces

Hannes Reinecke hare at suse.de
Tue Feb 22 01:39:20 PST 2022


On 2/22/22 09:54, Aleksandr Dyadyushkin wrote:
> From: Aleksandr Dyadyushkin <alextalker at yandex.ru>
> 
> Allow the end user (i.e. the administrator) to set maximum number of
> namespaces (and thus NN and MNAN implicitly) via module loading-time
> parameter, without a need to modify and rebuild source code.
> 
> Most of all this can be helpful for mock-up configurations and possibly
> really sparse NSID assignments.
> 
> For backwards compatibility, default values are left as is.
> 
> While permitted values are choosen as high as possible for the current
> code architecture and standard limitations, it is worth noting that
> allocations at 'nvmet_execute_get_log_page_ana' might yield a failure in
> runtime on systems with high parameter value and low free memory.
> 
> Signed-off-by: Aleksandr Dyadyushkin <alextalker at ya.ru>
> ---
>   drivers/nvme/target/admin-cmd.c |  6 +++---
>   drivers/nvme/target/core.c      | 28 +++++++++++++++++++++++++++-
>   drivers/nvme/target/nvmet.h     |  2 ++
>   3 files changed, 32 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
> index 6fb24746de06..940297233986 100644
> --- a/drivers/nvme/target/admin-cmd.c
> +++ b/drivers/nvme/target/admin-cmd.c
> @@ -278,7 +278,7 @@ static void nvmet_execute_get_log_page_ana(struct nvmet_req *req)
>   	u16 status;
>   
>   	status = NVME_SC_INTERNAL;
> -	desc = kmalloc(struct_size(desc, nsids, NVMET_MAX_NAMESPACES),
> +	desc = kmalloc(struct_size(desc, nsids, nvmet_max_namespaces),
>   		       GFP_KERNEL);
>   	if (!desc)
>   		goto out;
> @@ -428,8 +428,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
>   	/* no enforcement soft-limit for maxcmd - pick arbitrary high value */
>   	id->maxcmd = cpu_to_le16(NVMET_MAX_CMD);
>   
> -	id->nn = cpu_to_le32(NVMET_MAX_NAMESPACES);
> -	id->mnan = cpu_to_le32(NVMET_MAX_NAMESPACES);
> +	id->nn = cpu_to_le32(nvmet_max_namespaces);
> +	id->mnan = cpu_to_le32(nvmet_max_namespaces);
>   	id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM |
>   			NVME_CTRL_ONCS_WRITE_ZEROES);
>   
> diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
> index 5119c687de68..1b925b40074d 100644
> --- a/drivers/nvme/target/core.c
> +++ b/drivers/nvme/target/core.c
> @@ -15,6 +15,32 @@
>   
>   #include "nvmet.h"
>   
> +static int max_namespaces_set(const char *val, const struct kernel_param *kp);
> +static const struct kernel_param_ops max_namespaces_ops = {
> +	.set = max_namespaces_set,
> +	.get = param_get_uint,
> +};
> +
> +/* Account for 0h NSID */
> +#define NVMET_NSID_MAX (NVME_NSID_ALL - 1)
> +
> +u32 nvmet_max_namespaces = NVMET_MAX_NAMESPACES;
> +module_param_cb(max_namespaces, &max_namespaces_ops, &nvmet_max_namespaces, 0444);
> +MODULE_PARM_DESC(max_namespaces, "Set maximum number of namespaces per subsystem (default: 1024)");
> +
> +static int max_namespaces_set(const char *val, const struct kernel_param *kp) {
> +	int ret;
> +	u32 n;
> +
> +	ret = kstrtouint(val, 10, &n);
> +	if (ret != 0)
> +		return -EINVAL;
> +	if (n == 0 || n >= NVMET_NSID_MAX)
> +		return -EINVAL;
> +
> +	return param_set_uint(val, kp);
> +}
> +
>   struct workqueue_struct *buffered_io_wq;
>   struct workqueue_struct *zbd_wq;
>   static const struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX];
> @@ -562,7 +588,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
>   		goto out_unlock;
>   
>   	ret = -EMFILE;
> -	if (subsys->nr_namespaces == NVMET_MAX_NAMESPACES)
> +	if (subsys->nr_namespaces == nvmet_max_namespaces)
>   		goto out_unlock;
>   
>   	ret = nvmet_bdev_ns_enable(ns);
> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
> index af193423c10b..ed4873963cc3 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -506,6 +506,8 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
>    */
>   #define NVMET_MAX_NAMESPACES	1024
>   
> +extern u32 nvmet_max_namespaces;
> +
>   /*
>    * 0 is not a valid ANA group ID, so we start numbering at 1.
>    *

Please make this a subsystem attribute.
That's precisely why we have configfs :-)

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare at suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer



More information about the Linux-nvme mailing list