Commit a51afb54 authored by Keith Busch's avatar Keith Busch Committed by Matthew Wilcox

NVMe: Fix nvme get/put queue semantics

The routines to get and lock nvme queues required the caller to "put"
or "unlock" them even if getting one returned NULL. This patch fixes that.
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarMatthew Wilcox <matthew.r.wilcox@intel.com>
parent de672b97
...@@ -285,9 +285,17 @@ static struct nvme_queue *raw_nvmeq(struct nvme_dev *dev, int qid) ...@@ -285,9 +285,17 @@ static struct nvme_queue *raw_nvmeq(struct nvme_dev *dev, int qid)
static struct nvme_queue *get_nvmeq(struct nvme_dev *dev) __acquires(RCU) static struct nvme_queue *get_nvmeq(struct nvme_dev *dev) __acquires(RCU)
{ {
struct nvme_queue *nvmeq;
unsigned queue_id = get_cpu_var(*dev->io_queue); unsigned queue_id = get_cpu_var(*dev->io_queue);
rcu_read_lock(); rcu_read_lock();
return rcu_dereference(dev->queues[queue_id]); nvmeq = rcu_dereference(dev->queues[queue_id]);
if (nvmeq)
return nvmeq;
rcu_read_unlock();
put_cpu_var(*dev->io_queue);
return NULL;
} }
static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU) static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
...@@ -299,8 +307,15 @@ static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU) ...@@ -299,8 +307,15 @@ static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
static struct nvme_queue *lock_nvmeq(struct nvme_dev *dev, int q_idx) static struct nvme_queue *lock_nvmeq(struct nvme_dev *dev, int q_idx)
__acquires(RCU) __acquires(RCU)
{ {
struct nvme_queue *nvmeq;
rcu_read_lock(); rcu_read_lock();
return rcu_dereference(dev->queues[q_idx]); nvmeq = rcu_dereference(dev->queues[q_idx]);
if (nvmeq)
return nvmeq;
rcu_read_unlock();
return NULL;
} }
static void unlock_nvmeq(struct nvme_queue *nvmeq) __releases(RCU) static void unlock_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
...@@ -809,7 +824,6 @@ static void nvme_make_request(struct request_queue *q, struct bio *bio) ...@@ -809,7 +824,6 @@ static void nvme_make_request(struct request_queue *q, struct bio *bio)
int result = -EBUSY; int result = -EBUSY;
if (!nvmeq) { if (!nvmeq) {
put_nvmeq(NULL);
bio_endio(bio, -EIO); bio_endio(bio, -EIO);
return; return;
} }
...@@ -884,10 +898,8 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx, ...@@ -884,10 +898,8 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,
struct nvme_queue *nvmeq; struct nvme_queue *nvmeq;
nvmeq = lock_nvmeq(dev, q_idx); nvmeq = lock_nvmeq(dev, q_idx);
if (!nvmeq) { if (!nvmeq)
unlock_nvmeq(nvmeq);
return -ENODEV; return -ENODEV;
}
cmdinfo.task = current; cmdinfo.task = current;
cmdinfo.status = -EINTR; cmdinfo.status = -EINTR;
...@@ -912,9 +924,10 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx, ...@@ -912,9 +924,10 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,
if (cmdinfo.status == -EINTR) { if (cmdinfo.status == -EINTR) {
nvmeq = lock_nvmeq(dev, q_idx); nvmeq = lock_nvmeq(dev, q_idx);
if (nvmeq) if (nvmeq) {
nvme_abort_command(nvmeq, cmdid); nvme_abort_command(nvmeq, cmdid);
unlock_nvmeq(nvmeq); unlock_nvmeq(nvmeq);
}
return -EINTR; return -EINTR;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment