From c5dfcc7f3d3f79688dbf06aeb099f1a036f42bb9 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Krivenok" <krivenok.dmitry@gmail.com>
Date: Tue, 28 Apr 2015 00:39:21 +0300
Subject: [PATCH 1/1] null_blk: fix handling of BLKPREP_DEFER case
This is a fix for BLKPREP_DEFER case in single queue mode.
It's rework of original implementation based on feedback
from Jens (basically his version plus locking fix).
Signed-off-by: Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
---
drivers/block/null_blk.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
@@ -24,6 +24,7 @@ struct nullb_queue {
wait_queue_head_t wait;
unsigned int queue_depth;
+ struct nullb *dev;
struct nullb_cmd *cmds;
};
@@ -153,6 +154,16 @@ static void put_tag(struct nullb_queue *nq, unsigned int tag)
if (waitqueue_active(&nq->wait))
wake_up(&nq->wait);
+
+ if (queue_mode == NULL_Q_RQ) {
+ struct nullb *nullb = nq->dev;
+
+ if (blk_queue_stopped(nullb->q)) {
+ spin_lock_irq(nullb->q->queue_lock);
+ blk_start_queue(nullb->q);
+ spin_unlock_irq(nullb->q->queue_lock);
+ }
+ }
}
static unsigned int get_tag(struct nullb_queue *nq)
@@ -196,7 +207,7 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait)
cmd = __alloc_cmd(nq);
if (cmd || !can_wait)
- return cmd;
+ goto out;
do {
prepare_to_wait(&nq->wait, &wait, TASK_UNINTERRUPTIBLE);
@@ -208,6 +219,11 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait)
} while (1);
finish_wait(&nq->wait, &wait);
+out:
+ if (!cmd) {
+ BUG_ON(queue_mode != NULL_Q_RQ);
+ blk_stop_queue(nq->dev->q);
+ }
return cmd;
}
@@ -372,6 +388,7 @@ static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
init_waitqueue_head(&nq->wait);
nq->queue_depth = nullb->queue_depth;
+ nq->dev = nullb;
}
static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
--
2.3.6