Skip to content

Commit

Permalink
NVMe: Fix nvme get/put queue semantics
Browse files Browse the repository at this point in the history
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: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
  • Loading branch information
Keith Busch authored and Matthew Wilcox committed Jun 4, 2014
1 parent de672b9 commit a51afb5
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions drivers/block/nvme-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct nvme_queue *nvmeq;
unsigned queue_id = get_cpu_var(*dev->io_queue);

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)
Expand All @@ -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)
__acquires(RCU)
{
struct nvme_queue *nvmeq;

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)
Expand Down Expand Up @@ -809,7 +824,6 @@ static void nvme_make_request(struct request_queue *q, struct bio *bio)
int result = -EBUSY;

if (!nvmeq) {
put_nvmeq(NULL);
bio_endio(bio, -EIO);
return;
}
Expand Down Expand Up @@ -884,10 +898,8 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,
struct nvme_queue *nvmeq;

nvmeq = lock_nvmeq(dev, q_idx);
if (!nvmeq) {
unlock_nvmeq(nvmeq);
if (!nvmeq)
return -ENODEV;
}

cmdinfo.task = current;
cmdinfo.status = -EINTR;
Expand All @@ -912,9 +924,10 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,

if (cmdinfo.status == -EINTR) {
nvmeq = lock_nvmeq(dev, q_idx);
if (nvmeq)
if (nvmeq) {
nvme_abort_command(nvmeq, cmdid);
unlock_nvmeq(nvmeq);
unlock_nvmeq(nvmeq);
}
return -EINTR;
}

Expand Down

0 comments on commit a51afb5

Please sign in to comment.