[PATCH] nvmet: don't change model_number on live subsys

Chaitanya Kulkarni
2021-02-18T03:17:07Z

When subsys is connected to the controller(s) right now user can change
the model_number. Add a check to make sure subsys is not connected
before we allow the change in model number from configfs.

Reported-by: Max Gurtovoy <mgurtovoy@nvidia.com>
Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
---

Without this patch :-

# echo "transport=loop,nqn=x" > /dev/nvme-fabrics
# nvme list | tr -s ' ' ' '
Node SN Model Namespace Usage Format FW Rev
/dev/nvme1n1 d86964f000f47541 Linux 1 1.07 GB / 1.07 GB 512 B + 0 B 5.11.0-r
#
# echo "NEW MODEL" > /sys/kernel/config/nvmet/subsystems/x/attr_model
# nvme list | tr -s ' ' ' '
Node SN Model Namespace Usage Format FW Rev
/dev/nvme1n1 d86964f000f47541 NEW MODEL 1 1.07 GB / 1.07 GB 512 B + 0 B 5.11.0-r
^^^^^^^^^
Problem above.
# nvme disconnect -n x
NQN:x disconnected 1 controller(s)

With this patch :-

# echo "transport=loop,nqn=x" > /dev/nvme-fabrics
# nvme list | tr -s ' ' ' '
Node SN Model Namespace Usage Format FW Rev
/dev/nvme1n1 decfcb968deb004d Linux 1 1.07 GB / 1.07 GB 512 B + 0 B 5.11.0-r
#
# echo "NEW MODEL" > /sys/kernel/config/nvmet/subsystems/x/attr_model
bash: echo: write error: Invalid argument
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Don't allow new value for the model to be set when connected.

# nvme disconnect -n x
NQN:x disconnected 1 controller(s)
# echo "NEW MODEL" > /sys/kernel/config/nvmet/subsystems/x/attr_model
# echo "transport=loop,nqn=x" > /dev/nvme-fabrics
# nvme list | tr -s ' ' ' '
Node SN Model Namespace Usage Format FW Rev
/dev/nvme1n1 decfcb968deb004d NEW MODEL 1 1.07 GB / 1.07 GB 512 B + 0 B 5.11.0-r
---

drivers/nvme/target/configfs.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 635a7cb45d0b..e0140a793d14 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1138,6 +1138,21 @@ static bool nvmet_is_ascii(const char c)
return c >= 0x20 && c <= 0x7e;
}

+static bool nvmet_subsys_is_connected(struct nvmet_subsys *subsys)
+{
+ struct nvmet_ctrl *ctrl;
+ bool connected = false;
+
+ mutex_lock(&subsys->lock);
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
+ connected = true;
+ break;
+ }
+ mutex_unlock(&subsys->lock);
+
+ return connected;
+}
+
static ssize_t nvmet_subsys_attr_model_store(struct config_item *item,
const char *page, size_t count)
{
@@ -1146,6 +1161,9 @@ static ssize_t nvmet_subsys_attr_model_store(struct config_item *item,
char *new_model_number;
int pos = 0, len;

+ if (nvmet_subsys_is_connected(subsys))
+ return -EINVAL;
+
len = strcspn(page, "\n");
if (!len)
return -EINVAL;
--
2.22.1