Re: [PATCH v5] blk-mq: Avoid that a completion can be ignored for BLK_EH_RESET_TIMER

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2018-04-11 at 16:19 +0300, Sagi Grimberg wrote:
> >   static void __blk_mq_requeue_request(struct request *rq)
> >   {
> >   	struct request_queue *q = rq->q;
> > +	enum mq_rq_state old_state = blk_mq_rq_state(rq);
> >   
> >   	blk_mq_put_driver_tag(rq);
> >   
> >   	trace_block_rq_requeue(q, rq);
> >   	wbt_requeue(q->rq_wb, &rq->issue_stat);
> >   
> > -	if (blk_mq_rq_state(rq) != MQ_RQ_IDLE) {
> > -		blk_mq_rq_update_state(rq, MQ_RQ_IDLE);
> > +	if (old_state != MQ_RQ_IDLE) {
> > +		if (!blk_mq_change_rq_state(rq, old_state, MQ_RQ_IDLE))
> > +			WARN_ON_ONCE(true);
> >   		if (q->dma_drain_size && blk_rq_bytes(rq))
> >   			rq->nr_phys_segments--;
> >   	}
> 
> Can you explain why was old_state kept as a local variable?

Hello Sagi,

Since blk_mq_requeue_request() must be called after a request has completed
the timeout handler will ignore requests that are being requeued. Hence it
is safe in this function to cache the request state in a local variable.

> > +static inline bool blk_mq_change_rq_state(struct request *rq,
> > +					  enum mq_rq_state old_state,
> > +					  enum mq_rq_state new_state)
> >   {
> > -	u64 old_val = READ_ONCE(rq->gstate);
> > -	u64 new_val = (old_val & ~MQ_RQ_STATE_MASK) | state;
> > -
> > -	if (state == MQ_RQ_IN_FLIGHT) {
> > -		WARN_ON_ONCE((old_val & MQ_RQ_STATE_MASK) != MQ_RQ_IDLE);
> > -		new_val += MQ_RQ_GEN_INC;
> > -	}
> > +	unsigned long old_val = (READ_ONCE(rq->__deadline) & ~RQ_STATE_MASK) |
> > +				old_state;
> > +	unsigned long new_val = (old_val & ~RQ_STATE_MASK) | new_state;
> >   
> > -	/* avoid exposing interim values */
> > -	WRITE_ONCE(rq->gstate, new_val);
> > +	return cmpxchg(&rq->__deadline, old_val, new_val) == old_val;
> >   }
> 
> Can you explain why this takes the old_state of the request?

Can you clarify your question? The purpose of this function is to change
the request state only into @new_state if it matches @old_state. I think
that is also what the implementation of this function does.

Thanks,

Bart.








[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]