]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/nvme/target/core.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / nvme / target / core.c
index a21437a33adbef0c51395c0b88f2e8a10995ea86..fc5ba2f9e15f47fe8bd13795bdb9d6caaa532b93 100644 (file)
@@ -200,7 +200,7 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
        pr_err("ctrl %d keep-alive timer (%d seconds) expired!\n",
                ctrl->cntlid, ctrl->kato);
 
-       ctrl->ops->delete_ctrl(ctrl);
+       nvmet_ctrl_fatal_error(ctrl);
 }
 
 static void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
@@ -264,7 +264,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
        int ret = 0;
 
        mutex_lock(&subsys->lock);
-       if (!list_empty(&ns->dev_link))
+       if (ns->enabled)
                goto out_unlock;
 
        ns->bdev = blkdev_get_by_path(ns->device_path, FMODE_READ | FMODE_WRITE,
@@ -309,6 +309,7 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
        list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
                nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, 0, 0);
 
+       ns->enabled = true;
        ret = 0;
 out_unlock:
        mutex_unlock(&subsys->lock);
@@ -325,11 +326,11 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
        struct nvmet_ctrl *ctrl;
 
        mutex_lock(&subsys->lock);
-       if (list_empty(&ns->dev_link)) {
-               mutex_unlock(&subsys->lock);
-               return;
-       }
-       list_del_init(&ns->dev_link);
+       if (!ns->enabled)
+               goto out_unlock;
+
+       ns->enabled = false;
+       list_del_rcu(&ns->dev_link);
        mutex_unlock(&subsys->lock);
 
        /*
@@ -351,6 +352,7 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
 
        if (ns->bdev)
                blkdev_put(ns->bdev, FMODE_WRITE|FMODE_READ);
+out_unlock:
        mutex_unlock(&subsys->lock);
 }
 
@@ -617,7 +619,7 @@ u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
        if (!subsys) {
                pr_warn("connect request for invalid subsystem %s!\n",
                        subsysnqn);
-               req->rsp->result = IPO_IATTR_CONNECT_DATA(subsysnqn);
+               req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn);
                return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
        }
 
@@ -638,7 +640,7 @@ u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
 
        pr_warn("could not find controller %d for subsys %s / host %s\n",
                cntlid, subsysnqn, hostnqn);
-       req->rsp->result = IPO_IATTR_CONNECT_DATA(cntlid);
+       req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid);
        status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
 
 out:
@@ -700,7 +702,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
        if (!subsys) {
                pr_warn("connect request for invalid subsystem %s!\n",
                        subsysnqn);
-               req->rsp->result = IPO_IATTR_CONNECT_DATA(subsysnqn);
+               req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn);
                goto out;
        }
 
@@ -709,7 +711,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
        if (!nvmet_host_allowed(req, subsys, hostnqn)) {
                pr_info("connect by host %s for subsystem %s not allowed\n",
                        hostnqn, subsysnqn);
-               req->rsp->result = IPO_IATTR_CONNECT_DATA(hostnqn);
+               req->rsp->result.u32 = IPO_IATTR_CONNECT_DATA(hostnqn);
                up_read(&nvmet_config_sem);
                goto out_put_subsystem;
        }
@@ -814,6 +816,9 @@ static void nvmet_ctrl_free(struct kref *ref)
        list_del(&ctrl->subsys_entry);
        mutex_unlock(&subsys->lock);
 
+       flush_work(&ctrl->async_event_work);
+       cancel_work_sync(&ctrl->fatal_err_work);
+
        ida_simple_remove(&subsys->cntlid_ida, ctrl->cntlid);
        nvmet_subsys_put(subsys);
 
@@ -933,6 +938,16 @@ static void nvmet_subsys_free(struct kref *ref)
        kfree(subsys);
 }
 
+void nvmet_subsys_del_ctrls(struct nvmet_subsys *subsys)
+{
+       struct nvmet_ctrl *ctrl;
+
+       mutex_lock(&subsys->lock);
+       list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
+               ctrl->ops->delete_ctrl(ctrl);
+       mutex_unlock(&subsys->lock);
+}
+
 void nvmet_subsys_put(struct nvmet_subsys *subsys)
 {
        kref_put(&subsys->ref, nvmet_subsys_free);