Re: [PATCH] scsi: Remove QUEUE_FLAG_REENTER from SCSI code

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

 



On Mon, Sep 27, 2010 at 04:58:13PM +0900, James Bottomley wrote:
> On Thu, 2010-09-02 at 17:01 +0200, Christof Schmitt wrote:
> > scsi_run_queue and fc_bsg_goose_queue try to call __blk_run_queue with
> > the flag QUEUE_FLAG_REENTER set. Since __blk_run_queue already sets
> > the flag internally, this part can be removed from the SCSI and FC
> > transport code. With this change, the function fc_bsg_goose_queue can
> > simply be replaced with a conditional call to blk_run_queue.
> 
> OK, so Hannes made me look at this again:
> 
> Actually, there is a problem here ... and the original code doesn't pick
> it up.  We could still be recursing unacceptably because the fc login
> interrupt can come in while we're running the block queue, but if it's
> not the rport queue (which it likely won't be) we won't see the
> recursion.
> 
> The actual solution is not to run the queue directly from the interrupt
> at all (and dink with the REENTER) flags, but simply to use the
> kblockd_schedule_work() API to cause the queue to be run in workqueue
> context.  Redo the patch like that and I'll apply it.
> 
> James

I spent some more time to understand the requirements of the flag
setting:

As far as i see, the FC rport bsg queue does not have the recursion
problem. fc_remote_port_add is the only caller of fc_bsg_goose_queue
and fc_remote_port_add has to be called from thread context. So,
fc_bsg_goose_queue can be reduced to a simple call to blk_run_queue.

scsi_run_queue has the recursion problem: It calls blk_run_queue that
can call the request_fn that in SCSI can recurse back to
scsi_queue_insert and scsi_run_queue.  The problem in commit
04846f25920d4b05d6040c531cc601049260db52 looks like a long list of
starved devices and each starved device entry adds to the stack.

So, the solution would be to:
1) Replace fc_bsg_goose_queue with a direkt call to blk_run_queue
2) As mentioned above, in scsi_run_queue defer the call to the block
   workqueue.

Is it worth adding a block layer function to keep the workqueue usage
in blk-core? Or simply open code the required steps in scsi_run_queue,
e.g.

queue_flag_set(QUEUE_FLAG_PLUGGED, q);
kblockd_schedule_work(q, &q->unplug_work);
?

Christof

> 
> 
> > Signed-off-by: Christof Schmitt <christof.schmitt@xxxxxxxxxx>
> > ---
> >  drivers/scsi/scsi_lib.c          |   15 +--------------
> >  drivers/scsi/scsi_transport_fc.c |   34 ++--------------------------------
> >  2 files changed, 3 insertions(+), 46 deletions(-)
> > 
> > --- a/drivers/scsi/scsi_lib.c
> > +++ b/drivers/scsi/scsi_lib.c
> > @@ -411,8 +411,6 @@ static void scsi_run_queue(struct reques
> >  	list_splice_init(&shost->starved_list, &starved_list);
> >  
> >  	while (!list_empty(&starved_list)) {
> > -		int flagset;
> > -
> >  		/*
> >  		 * As long as shost is accepting commands and we have
> >  		 * starved queues, call blk_run_queue. scsi_request_fn
> > @@ -436,18 +434,7 @@ static void scsi_run_queue(struct reques
> >  		}
> >  
> >  		spin_unlock(shost->host_lock);
> > -
> > -		spin_lock(sdev->request_queue->queue_lock);
> > -		flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
> > -				!test_bit(QUEUE_FLAG_REENTER,
> > -					&sdev->request_queue->queue_flags);
> > -		if (flagset)
> > -			queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
> > -		__blk_run_queue(sdev->request_queue);
> > -		if (flagset)
> > -			queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
> > -		spin_unlock(sdev->request_queue->queue_lock);
> > -
> > +		blk_run_queue(sdev->request_queue);
> >  		spin_lock(shost->host_lock);
> >  	}
> >  	/* put any unprocessed entries back */
> > --- a/drivers/scsi/scsi_transport_fc.c
> > +++ b/drivers/scsi/scsi_transport_fc.c
> > @@ -50,7 +50,6 @@ static int fc_vport_setup(struct Scsi_Ho
> >  static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
> >  static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
> >  static void fc_bsg_remove(struct request_queue *);
> > -static void fc_bsg_goose_queue(struct fc_rport *);
> >  
> >  /*
> >   * Redefine so that we can have same named attributes in the
> > @@ -2737,7 +2736,8 @@ fc_remote_port_add(struct Scsi_Host *sho
> >  					spin_unlock_irqrestore(shost->host_lock,
> >  							flags);
> >  
> > -				fc_bsg_goose_queue(rport);
> > +				if (rport->rqst_q)
> > +					blk_run_queue(rport->rqst_q);
> >  
> >  				return rport;
> >  			}
> > @@ -3752,36 +3752,6 @@ fail_host_msg:
> >  	return FC_DISPATCH_UNLOCKED;
> >  }
> >  
> > -
> > -/*
> > - * fc_bsg_goose_queue - restart rport queue in case it was stopped
> > - * @rport:	rport to be restarted
> > - */
> > -static void
> > -fc_bsg_goose_queue(struct fc_rport *rport)
> > -{
> > -	int flagset;
> > -	unsigned long flags;
> > -
> > -	if (!rport->rqst_q)
> > -		return;
> > -
> > -	get_device(&rport->dev);
> > -
> > -	spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
> > -	flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
> > -		  !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
> > -	if (flagset)
> > -		queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q);
> > -	__blk_run_queue(rport->rqst_q);
> > -	if (flagset)
> > -		queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
> > -	spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
> > -
> > -	put_device(&rport->dev);
> > -}
> > -
> > -
> >  /**
> >   * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
> >   * @q:		rport request queue
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux