On Wed, Mar 15, 2017 at 12:07:37AM +0000, Bart Van Assche wrote: > On Thu, 2017-03-09 at 21:02 +0800, Ming Lei wrote: > > diff --git a/block/blk-mq.c b/block/blk-mq.c > > index 159187a28d66..0aff380099d5 100644 > > --- a/block/blk-mq.c > > +++ b/block/blk-mq.c > > @@ -697,17 +697,8 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, > > { > > struct blk_mq_timeout_data *data = priv; > > > > - if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) { > > - /* > > - * If a request wasn't started before the queue was > > - * marked dying, kill it here or it'll go unnoticed. > > - */ > > - if (unlikely(blk_queue_dying(rq->q))) { > > - rq->errors = -EIO; > > - blk_mq_end_request(rq, rq->errors); > > - } > > + if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) > > return; > > - } > > > > if (time_after_eq(jiffies, rq->deadline)) { > > if (!blk_mark_rq_complete(rq)) > > Both the old and the new check look racy to me. The REQ_ATOM_STARTED bit can > be changed concurrently by blk_mq_start_request(), __blk_mq_finish_request() blk_mq_start_request() and __blk_mq_finish_request() won't be run concurrently. >From view of __blk_mq_finish_request(): - if it is run from merge queue io path(blk_mq_merge_queue_io()), blk_mq_start_request() can't be run at all, and the COMPLETE flag is kept as previous value(zero) - if it is run from normal complete path, COMPLETE flag is cleared before the req/tag is released to tag set. so there isn't race in blk_mq_start_request() vs. __blk_mq_finish_request() wrt. timeout. > or __blk_mq_requeue_request(). Another issue with this function is that the __blk_mq_requeue_request() can be run from two pathes: - dispatch failure, in which case the req/tag isn't released to tag set - IO completion path, in which COMPLETE flag is cleared before requeue. so I can't see races with timeout in case of start rq vs. requeue rq. > request passed to this function can be reinitialized concurrently. Sorry but Yes, that is possible, but rq->atomic_flags is kept, and in that case when we handle timeout, COMPLETE is cleared before releasing the rq/tag to tag set via blk_mark_rq_complete(), so we won't complete that req twice. Thanks, Ming