|
@@ -144,6 +144,42 @@ static void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
|
|
schedule_work(&ctrl->async_event_work);
|
|
schedule_work(&ctrl->async_event_work);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid)
|
|
|
|
+{
|
|
|
|
+ u32 i;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&ctrl->lock);
|
|
|
|
+ if (ctrl->nr_changed_ns > NVME_MAX_CHANGED_NAMESPACES)
|
|
|
|
+ goto out_unlock;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ctrl->nr_changed_ns; i++) {
|
|
|
|
+ if (ctrl->changed_ns_list[i] == nsid)
|
|
|
|
+ goto out_unlock;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ctrl->nr_changed_ns == NVME_MAX_CHANGED_NAMESPACES) {
|
|
|
|
+ ctrl->changed_ns_list[0] = cpu_to_le32(0xffffffff);
|
|
|
|
+ ctrl->nr_changed_ns = U32_MAX;
|
|
|
|
+ goto out_unlock;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ctrl->changed_ns_list[ctrl->nr_changed_ns++] = nsid;
|
|
|
|
+out_unlock:
|
|
|
|
+ mutex_unlock(&ctrl->lock);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid)
|
|
|
|
+{
|
|
|
|
+ struct nvmet_ctrl *ctrl;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry) {
|
|
|
|
+ nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid));
|
|
|
|
+ nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE,
|
|
|
|
+ NVME_AER_NOTICE_NS_CHANGED,
|
|
|
|
+ NVME_LOG_CHANGED_NS);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int nvmet_register_transport(const struct nvmet_fabrics_ops *ops)
|
|
int nvmet_register_transport(const struct nvmet_fabrics_ops *ops)
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
@@ -287,7 +323,6 @@ static void nvmet_ns_dev_disable(struct nvmet_ns *ns)
|
|
int nvmet_ns_enable(struct nvmet_ns *ns)
|
|
int nvmet_ns_enable(struct nvmet_ns *ns)
|
|
{
|
|
{
|
|
struct nvmet_subsys *subsys = ns->subsys;
|
|
struct nvmet_subsys *subsys = ns->subsys;
|
|
- struct nvmet_ctrl *ctrl;
|
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
mutex_lock(&subsys->lock);
|
|
mutex_lock(&subsys->lock);
|
|
@@ -326,9 +361,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
|
|
list_add_tail_rcu(&ns->dev_link, &old->dev_link);
|
|
list_add_tail_rcu(&ns->dev_link, &old->dev_link);
|
|
}
|
|
}
|
|
|
|
|
|
- list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
|
|
|
|
- nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, 0, 0);
|
|
|
|
-
|
|
|
|
|
|
+ nvmet_ns_changed(subsys, ns->nsid);
|
|
ns->enabled = true;
|
|
ns->enabled = true;
|
|
ret = 0;
|
|
ret = 0;
|
|
out_unlock:
|
|
out_unlock:
|
|
@@ -342,7 +375,6 @@ out_dev_put:
|
|
void nvmet_ns_disable(struct nvmet_ns *ns)
|
|
void nvmet_ns_disable(struct nvmet_ns *ns)
|
|
{
|
|
{
|
|
struct nvmet_subsys *subsys = ns->subsys;
|
|
struct nvmet_subsys *subsys = ns->subsys;
|
|
- struct nvmet_ctrl *ctrl;
|
|
|
|
|
|
|
|
mutex_lock(&subsys->lock);
|
|
mutex_lock(&subsys->lock);
|
|
if (!ns->enabled)
|
|
if (!ns->enabled)
|
|
@@ -368,9 +400,7 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
|
|
percpu_ref_exit(&ns->ref);
|
|
percpu_ref_exit(&ns->ref);
|
|
|
|
|
|
mutex_lock(&subsys->lock);
|
|
mutex_lock(&subsys->lock);
|
|
- list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
|
|
|
|
- nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, 0, 0);
|
|
|
|
-
|
|
|
|
|
|
+ nvmet_ns_changed(subsys, ns->nsid);
|
|
nvmet_ns_dev_disable(ns);
|
|
nvmet_ns_dev_disable(ns);
|
|
out_unlock:
|
|
out_unlock:
|
|
mutex_unlock(&subsys->lock);
|
|
mutex_unlock(&subsys->lock);
|
|
@@ -832,11 +862,16 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
|
|
kref_init(&ctrl->ref);
|
|
kref_init(&ctrl->ref);
|
|
ctrl->subsys = subsys;
|
|
ctrl->subsys = subsys;
|
|
|
|
|
|
|
|
+ ctrl->changed_ns_list = kmalloc_array(NVME_MAX_CHANGED_NAMESPACES,
|
|
|
|
+ sizeof(__le32), GFP_KERNEL);
|
|
|
|
+ if (!ctrl->changed_ns_list)
|
|
|
|
+ goto out_free_ctrl;
|
|
|
|
+
|
|
ctrl->cqs = kcalloc(subsys->max_qid + 1,
|
|
ctrl->cqs = kcalloc(subsys->max_qid + 1,
|
|
sizeof(struct nvmet_cq *),
|
|
sizeof(struct nvmet_cq *),
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|
|
if (!ctrl->cqs)
|
|
if (!ctrl->cqs)
|
|
- goto out_free_ctrl;
|
|
|
|
|
|
+ goto out_free_changed_ns_list;
|
|
|
|
|
|
ctrl->sqs = kcalloc(subsys->max_qid + 1,
|
|
ctrl->sqs = kcalloc(subsys->max_qid + 1,
|
|
sizeof(struct nvmet_sq *),
|
|
sizeof(struct nvmet_sq *),
|
|
@@ -894,6 +929,8 @@ out_free_sqs:
|
|
kfree(ctrl->sqs);
|
|
kfree(ctrl->sqs);
|
|
out_free_cqs:
|
|
out_free_cqs:
|
|
kfree(ctrl->cqs);
|
|
kfree(ctrl->cqs);
|
|
|
|
+out_free_changed_ns_list:
|
|
|
|
+ kfree(ctrl->changed_ns_list);
|
|
out_free_ctrl:
|
|
out_free_ctrl:
|
|
kfree(ctrl);
|
|
kfree(ctrl);
|
|
out_put_subsystem:
|
|
out_put_subsystem:
|
|
@@ -920,6 +957,7 @@ static void nvmet_ctrl_free(struct kref *ref)
|
|
|
|
|
|
kfree(ctrl->sqs);
|
|
kfree(ctrl->sqs);
|
|
kfree(ctrl->cqs);
|
|
kfree(ctrl->cqs);
|
|
|
|
+ kfree(ctrl->changed_ns_list);
|
|
kfree(ctrl);
|
|
kfree(ctrl);
|
|
|
|
|
|
nvmet_subsys_put(subsys);
|
|
nvmet_subsys_put(subsys);
|