summaryrefslogtreecommitdiff
path: root/drivers/block/nvme.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2011-02-07 12:45:24 -0500
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2011-11-04 15:52:56 -0400
commit9294bbed78926a895516ec016ba23033f58d1a88 (patch)
tree84eb4ea0d153e0ad6d7b629e867f9d93a39506b5 /drivers/block/nvme.c
parente85248e516c550382ba33ca325c272a0ca397e44 (diff)
NVMe: Handle the congestion list a little better
In the bio completion handler, check for bios on the congestion list for this NVM queue. Also, lock the congestion list in the make_request function as the queue may end up being shared between multiple CPUs. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block/nvme.c')
-rw-r--r--drivers/block/nvme.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index 60c1048dc8bc..2a0dd5e60347 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -105,6 +105,8 @@ struct nvme_queue {
unsigned long cmdid_data[];
};
+static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio);
+
/*
* Check we didin't inadvertently grow the command struct
*/
@@ -274,6 +276,9 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx,
bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
free_info(info);
bio_endio(bio, status ? -EIO : 0);
+ bio = bio_list_pop(&nvmeq->sq_cong);
+ if (bio)
+ nvme_resubmit_bio(nvmeq, bio);
}
/* length is in bytes */
@@ -392,6 +397,16 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
return -EBUSY;
}
+static void nvme_resubmit_bio(struct nvme_queue *nvmeq, struct bio *bio)
+{
+ struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data;
+ if (nvme_submit_bio_queue(nvmeq, ns, bio))
+ bio_list_add_head(&nvmeq->sq_cong, bio);
+ else if (bio_list_empty(&nvmeq->sq_cong))
+ blk_clear_queue_congested(ns->queue, rw_is_sync(bio->bi_rw));
+ /* XXX: Need to duplicate the logic from __freed_request here */
+}
+
/*
* NB: return value of non-zero would mean that we were a stacking driver.
* make_request must always succeed.
@@ -403,7 +418,9 @@ static int nvme_make_request(struct request_queue *q, struct bio *bio)
if (nvme_submit_bio_queue(nvmeq, ns, bio)) {
blk_set_queue_congested(q, rw_is_sync(bio->bi_rw));
+ spin_lock_irq(&nvmeq->q_lock);
bio_list_add(&nvmeq->sq_cong, bio);
+ spin_unlock_irq(&nvmeq->q_lock);
}
put_nvmeq(nvmeq);