Folks, any comments on this patch? Thanks, Dmitry On Sun, Apr 19, 2015 at 9:19 PM, Dmitry Krivenok <krivenok.dmitry@xxxxxxxxx> wrote: > When we fail to allocate new cmd in null_rq_prep_fn we return BLKPREP_DEFER > which is not handled properly. In single-queue mode of null_blk the following > command hangs forever in io_schedule(): > $ dd if=/dev/nullb0 of=/dev/null bs=8M count=5000 iflag=direct > > The reason is that when 64 commands have been allocated, the 65th command > allocation will fail due to missing free tag. The request, however, will be > kept in the queue which will never be started again (unless you run another > command that does I/O to /dev/nullb0). > > This small patch tries to solve the issue by stopping the queue when we > detect that all tags were exhausted and starting it again when we free the tag. > > I've verified that the command mentioned above doesn't hang anymore and also > made sure that null_blk with my change survives fio-based stress tests. > > Signed-off-by: Dmitry V. Krivenok <krivenok.dmitry@xxxxxxxxx> > --- > drivers/block/null_blk.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c > index 65cd61a..4ac684b 100644 > --- a/drivers/block/null_blk.c > +++ b/drivers/block/null_blk.c > @@ -25,6 +25,7 @@ struct nullb_queue { > unsigned int queue_depth; > > struct nullb_cmd *cmds; > + bool no_cmds; > }; > > struct nullb { > @@ -171,6 +172,13 @@ static unsigned int get_tag(struct nullb_queue *nq) > static void free_cmd(struct nullb_cmd *cmd) > { > put_tag(cmd->nq, cmd->tag); > + if(cmd->nq->no_cmds) { > + unsigned long flags; > + cmd->nq->no_cmds = false; > + spin_lock_irqsave(cmd->rq->q->queue_lock, flags); > + blk_start_queue(cmd->rq->q); > + spin_unlock_irqrestore(cmd->rq->q->queue_lock, flags); > + } > } > > static struct nullb_cmd *__alloc_cmd(struct nullb_queue *nq) > @@ -195,6 +203,9 @@ static struct nullb_cmd *alloc_cmd(struct > nullb_queue *nq, int can_wait) > DEFINE_WAIT(wait); > > cmd = __alloc_cmd(nq); > + if (!cmd && !can_wait) { > + nq->no_cmds = true; > + } > if (cmd || !can_wait) > return cmd; > > @@ -341,6 +352,7 @@ static int null_rq_prep_fn(struct request_queue > *q, struct request *req) > static void null_request_fn(struct request_queue *q) > { > struct request *rq; > + struct nullb_queue *nq = nullb_to_queue(q->queuedata); > > while ((rq = blk_fetch_request(q)) != NULL) { > struct nullb_cmd *cmd = rq->special; > @@ -349,6 +361,9 @@ static void null_request_fn(struct request_queue *q) > null_handle_cmd(cmd); > spin_lock_irq(q->queue_lock); > } > + if(nq->no_cmds) { > + blk_stop_queue(q); > + } > } > > static int null_queue_rq(struct blk_mq_hw_ctx *hctx, > @@ -430,6 +445,7 @@ static int setup_commands(struct nullb_queue *nq) > if (!nq->cmds) > return -ENOMEM; > > + nq->no_cmds = false; > tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG; > nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL); > if (!nq->tag_map) { > -- > 2.3.5 -- Sincerely yours, Dmitry V. Krivenok e-mail: krivenok.dmitry@xxxxxxxxx skype: krivenok_dmitry jabber: krivenok_dmitry@xxxxxxxxx icq: 242-526-443 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html