linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff
@ 2005-03-31  9:07 Tejun Heo
  2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
                   ` (12 more replies)
  0 siblings, 13 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:07 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

 Hello, James.
 Hello, Jens.

 This patchset is consisted of three parts

 #01-#06: Misc updates.  Except for #02, all patches are from the last
	  patchset.  #05 has been updated.
 #07-#10: Rewrite scsi_request_fn().
 #11-#13: Consolidate requeue paths & cleanup scsi_cmd_retry() calls
	  in scsi_error.c.

#01-#06: Subset of the previously posted misc patchset
----------------------------------------------------------------------
 The new patch #02 removes the code which sets REQ_SPECIAL when
sgtable allocation fails in scsi_init_io().

 #05 timer_cleanup is updated like the following.

	* scsi_eh_times_out() now clears eh_timeout.function.  The
	  original patch triggers BUG() when eh command times out.
	  This fixes the bug.
	* scsi_times_out() doesn't clear eh_timeout.data.
	* In scsi_dispatch_cmd(), when queuecommand fails, iodone_cnt
	  is bumped up only if timer deletion succeeds.

 #01, #03-#04 and #06 are unchanged from the previous posting.

 Note: Patches from the previous patchset which are pointed out to be
       problemetic are omitted.

#07-#10: Rewrite scsi_request_fn().
----------------------------------------------------------------------
 These patches rewrites functions related to command issuing.  The big
picture is

 * scsi_prep_fn(): Only preps requests.  No deferring/killing happens
	in this function unless the request is invalid.  And all
	invalid requests are terminated here.  No invalid request
	reaches request_fn.
 * scsi_request_fn(): Switch locks only once per each issuing.  Don't
	use more than one paths to do the same thing (unified defer
	and kill paths).  Don't test for the same condition multiple
	times.  Make as concise as possible.

#11-#13: Consolidate requeue paths & cleanup scsi_cmd_retry() calls.
----------------------------------------------------------------------
 See patch descriptions.

[ Start of patch descriptions ]

01_scsi_no_REQ_SPECIAL_on_requeue.patch
	: don't use blk_insert_request() for requeueing

	blk_insert_request() has 'reinsert' argument, which, when set,
	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
	request.  SCSI midlayer was the only user of this feature and
	all requeued requests become special requests defeating
	quiesce state.  This patch makes scsi midlayer use
	blk_requeue_request() for requeueing and removes 'reinsert'
	feature from blk_insert_request().

	Note: In drivers/scsi/scsi_lib.c, scsi_single_lun_run() and
	scsi_run_queue() are moved upward unchanged.

02_scsi_no_REQ_SPECIAL_on_sgtable_allocation_failure.patch
	: don't turn on REQ_SPECIAL on sgtable allocation failure.

	Don't turn on REQ_SPECIAL on sgtable allocation failure.  This
	was the last place where REQ_SPECIAL is turned on for normal
	requests.

03_scsi_remove_internal_timeout.patch
	: remove unused scsi_cmnd->internal_timeout field

	scsi_cmnd->internal_timeout field doesn't have any meaning
	anymore.  Kill the field.

04_scsi_remove_volatile.patch
	: remove meaningless volatile qualifiers from structure definitions

	scsi_device->device_busy, Scsi_Host->host_busy and
	->host_failed have volatile qualifiers, but the qualifiers
	don't serve any purpose.  Kill them.  While at it, protect
	->host_failed update in scsi_error for consistency and clarity.

05_scsi_timer_cleanup.patch
	: remove a timer race from scsi_queue_insert() and cleanup timer

	scsi_queue_insert() has four callers.  Three callers call with
	timer disabled and one (the second invocation in
	scsi_dispatch_cmd()) calls with timer activated.
	scsi_queue_insert() used to always call scsi_delete_timer()
	and ignore the return value.  This results in race with timer
	expiration.  Remove scsi_delete_timer() call from
	scsi_queue_insert() and make the caller delete timer and check
	the return value.

	While at it, as, once a scsi timer is added, it should expire
	or be deleted before reused, make scsi_add_timer() strict
	about timer reuses.  Now timer expiration function should
	clear ->function and all timer deletion should go through
	scsi_delete_timer().  Also, remove bogus ->eh_action tests
	from scsi_eh_{done|times_out} functions.  The condition is
	always true and the test is somewhat misleading.

06_scsi_remove_serial_number_at_timeout.patch
	: remove meaningless scsi_cmnd->serial_number_at_timeout field

	scsi_cmnd->serial_number_at_timeout doesn't serve any purpose
	anymore.  All serial_number == serial_number_at_timeout tests
	are always true in abort callbacks.  Kill the field.  Also, as
	->pid always equals ->serial_number and ->serial_number
	doesn't have any special meaning anymore, update comments
	above ->serial_number accordingly.  Once we remove all uses of
	this field from all lldd's, this field should go.

07_scsi_consolidate_prep_fn_error_handling.patch
	: move error handling out of scsi_init_io() into scsi_prep_fn()

	When scsi_init_io() returns BLKPREP_DEFER or BLKPREP_KILL,
	it's supposed to free resources itself.  This patch
	consolidates defer and kill handling into scsi_prep_fn().
	This fixes a queue stall bug which occurred when sgtable
	allocation failed and device_busy == 0.

08_scsi_move_preps_to_prep_fn.patch
	: move request preps in other places into prep_fn()

	Move request preparations scattered in scsi_request_fn() and
	scsi_dispatch_cmd() into scsi_prep_fn().

	* CDB_SIZE check in scsi_dispatch_cmd()
	* SCSI-2 LUN preparation in scsi_dispatch_cmd()
	* scsi_init_cmd_errh() in scsi_request_fn()

	No invalid request reaches scsi_request_fn() anymore.

09_scsi_prep_fn_comment_update.patch
	: in scsi_prep_fn(), remove bogus comments & clean up

	Remove bogus comments from scsi_prep_fn() and clean up a bit.
	While at it, remove leading and tailing empty comment lines
	for one or two liners to make the code more concise.

10_scsi_request_fn_rewrite.patch
	: rewrite scsi_request_fn()

	This patch rewrites scsi_request_fn().  scsi_dispatch_cmd() is
	merged into scsi_request_fn().  Goals are

	* Remove unnecessary operations (host_lock unlocking/locking,
	  recursing into scsi_run_queue(), ...)
	* Consolidate defer/kill paths.
	* Be concise.

	The following changes fix bugs.

	* All killed requests now get fully prep'ed and pass through
	  __scsi_done().  This is the only kill path.
		- scsi_cmnd leak in offline-kill path removed
		- unfinished request bug in
		  scsi_dispatch_cmd():SDEV_DEL-kill path removed.
		- commands are never terminated directly from blk
		  layer unless they are invalid, so no need to supply
		  req->end_io callback for special requests.
	* Timer is added while holding host_lock, after all conditions
	  are checked and serial number is assigned.  This guarantees
	  that until host_lock is released, the scsi_cmnd pointed to
	  by cmd isn't released.  That didn't hold in the original
	  code and, theoretically, the original code could access
	  already released cmd.
	* For the same reason, if shost->hostt->queuecommand() fails,
	  we try to delete the timer before releasing host_lock.

	Other changes/notes

	* host_lock is acquired and released only once.
	  enter (qlocked) -> enter loop -> dev-prep -> switch to hlock -\
	                  ^---- switch to qlock <- issue <- host-prep <-/
	* unnecessary if () on get_device() removed.
	* loop on elv_next_request() instead of blk_queue_plugged().
	  We now explicitly break out of loop when we plug and check if
	  the queue has been plugged underneath us at the end of loop.
	* All device/host state checks are done in this function and
	  done only once while holding qlock/host_lock respectively.
	* Requests which get deferred during dev-prep are never
	  removed from request queue, so deferring is achieved by
	  simply breaking out of the loop and returning.
	* Failure of blk_queue_start_tag() on tagged queue is a BUG
	  now.  This condition should have been catched by
	  scsi_dev_queue_ready().
	* req->special == NULL test removed.  This just can't happen,
	  and even if it ever happens, scsi_request_fn() will
	  deterministically oops.
	* Requests which gets deferred during host-prep are requeued
	  using blk_requeue_request().  This is the only requeue path.

11_scsi_make_requeue_command_public.patch
	: add reprep arg to scsi_requeue_command() and make it public

	Add reprep argument to scsi_requeue_command(), remove
	redundant q argument, add code to set cmd->state/owner, and
	make the function public.  This patch is preparation for
	consolidating requeue paths.

12_scsi_consolidate_requeue_paths.patch
	: replace scsi_queue_insert() with scsi_requeue_command()

	Add scsi_device_unbusy() call to scsi_retry_command(), replace
	scsi_queue_insert() with scsi_requeue_command(), make
	scsi_softirq() use scsi_retry_command() for ADD_TO_MLQUEUE
	case too (with explicit device blocking), and make
	scsi_eh_flush_done_q() use scsi_retry_command().  While at it,
	remove leading and tailing empty comment lines from trivial
	comments.

	As scsi_queue_insert() has no users now, kill it.

13_scsi_consolidate_cmd_retry_calls_in_eh.patch
	: consolidate scsi_cmd_retry() calls in scsi_error.c

	Replace all scsi_setup_cmd_retry() calls in scsi_error.c with
	a call just above scsi_finish_command() in scsi_eh_flush_done_q().

[ End of patch descriptions ]

 I've cross-checked with the original source to avoid missing used
paths and proof-read the new code a couple of times.  I've tested
normal, failure and unplug paths with usb and sata drives (I can
reproduce timeouts easily with my usb hd).  Not that the code is
bug-free, but just that I tried.  :-)

 If you don't like removing of empty comment lines from short
comments, let me know, I'll restore the changes and repost the
patches.

 Also, as I'm basing new implementation of scsi device states on the
new request_fn(), it would be great if you can let me know if you like
the general direction of this patchset soon.

 Thanks a lot.

--
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
@ 2005-03-31  9:07 ` Tejun Heo
  2005-03-31 10:12   ` Christoph Hellwig
  2005-03-31 17:53   ` James Bottomley
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure Tejun Heo
                   ` (11 subsequent siblings)
  12 siblings, 2 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:07 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

01_scsi_no_REQ_SPECIAL_on_requeue.patch

	blk_insert_request() has 'reinsert' argument, which, when set,
	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
	request.  SCSI midlayer was the only user of this feature and
	all requeued requests become special requests defeating
	quiesce state.  This patch makes scsi midlayer use
	blk_requeue_request() for requeueing and removes 'reinsert'
	feature from blk_insert_request().

	Note: In drivers/scsi/scsi_lib.c, scsi_single_lun_run() and
	scsi_run_queue() are moved upward unchanged.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 drivers/block/ll_rw_blk.c |   20 +--
 drivers/block/paride/pd.c |    2 
 drivers/block/sx8.c       |    4 
 drivers/scsi/scsi_lib.c   |  238 +++++++++++++++++++++++-----------------------
 include/linux/blkdev.h    |    2 
 5 files changed, 133 insertions(+), 133 deletions(-)

Index: scsi-export/drivers/block/ll_rw_blk.c
===================================================================
--- scsi-export.orig/drivers/block/ll_rw_blk.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/block/ll_rw_blk.c	2005-03-31 18:06:19.000000000 +0900
@@ -2028,7 +2028,6 @@ EXPORT_SYMBOL(blk_requeue_request);
  * @rq:		request to be inserted
  * @at_head:	insert request at head or tail of queue
  * @data:	private data
- * @reinsert:	true if request it a reinsertion of previously processed one
  *
  * Description:
  *    Many block devices need to execute commands asynchronously, so they don't
@@ -2043,8 +2042,9 @@ EXPORT_SYMBOL(blk_requeue_request);
  *    host that is unable to accept a particular command.
  */
 void blk_insert_request(request_queue_t *q, struct request *rq,
-			int at_head, void *data, int reinsert)
+			int at_head, void *data)
 {
+	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 	unsigned long flags;
 
 	/*
@@ -2061,20 +2061,12 @@ void blk_insert_request(request_queue_t 
 	/*
 	 * If command is tagged, release the tag
 	 */
-	if (reinsert)
-		blk_requeue_request(q, rq);
-	else {
-		int where = ELEVATOR_INSERT_BACK;
+	if (blk_rq_tagged(rq))
+		blk_queue_end_tag(q, rq);
 
-		if (at_head)
-			where = ELEVATOR_INSERT_FRONT;
+	drive_stat_acct(rq, rq->nr_sectors, 1);
+	__elv_add_request(q, rq, where, 0);
 
-		if (blk_rq_tagged(rq))
-			blk_queue_end_tag(q, rq);
-
-		drive_stat_acct(rq, rq->nr_sectors, 1);
-		__elv_add_request(q, rq, where, 0);
-	}
 	if (blk_queue_plugged(q))
 		__generic_unplug_device(q);
 	else
Index: scsi-export/drivers/block/paride/pd.c
===================================================================
--- scsi-export.orig/drivers/block/paride/pd.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/block/paride/pd.c	2005-03-31 18:06:19.000000000 +0900
@@ -723,7 +723,7 @@ static int pd_special_command(struct pd_
 	rq.ref_count = 1;
 	rq.waiting = &wait;
 	rq.end_io = blk_end_sync_rq;
-	blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
+	blk_insert_request(disk->gd->queue, &rq, 0, func);
 	wait_for_completion(&wait);
 	rq.waiting = NULL;
 	if (rq.errors)
Index: scsi-export/drivers/block/sx8.c
===================================================================
--- scsi-export.orig/drivers/block/sx8.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/block/sx8.c	2005-03-31 18:06:19.000000000 +0900
@@ -614,7 +614,7 @@ static int carm_array_info (struct carm_
 	spin_unlock_irq(&host->lock);
 
 	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq);
 
 	return 0;
 
@@ -653,7 +653,7 @@ static int carm_send_special (struct car
 	crq->msg_bucket = (u32) rc;
 
 	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq);
 
 	return 0;
 }
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:19.000000000 +0900
@@ -65,6 +65,109 @@ struct scsi_host_sg_pool scsi_sg_pools[]
 
 
 /*
+ * Called for single_lun devices on IO completion. Clear starget_sdev_user,
+ * and call blk_run_queue for all the scsi_devices on the target -
+ * including current_sdev first.
+ *
+ * Called with *no* scsi locks held.
+ */
+static void scsi_single_lun_run(struct scsi_device *current_sdev)
+{
+	struct Scsi_Host *shost = current_sdev->host;
+	struct scsi_device *sdev, *tmp;
+	struct scsi_target *starget = scsi_target(current_sdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	starget->starget_sdev_user = NULL;
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	/*
+	 * Call blk_run_queue for all LUNs on the target, starting with
+	 * current_sdev. We race with others (to set starget_sdev_user),
+	 * but in most cases, we will be first. Ideally, each LU on the
+	 * target would get some limited time or requests on the target.
+	 */
+	blk_run_queue(current_sdev->request_queue);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (starget->starget_sdev_user)
+		goto out;
+	list_for_each_entry_safe(sdev, tmp, &starget->devices,
+			same_target_siblings) {
+		if (sdev == current_sdev)
+			continue;
+		if (scsi_device_get(sdev))
+			continue;
+
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		blk_run_queue(sdev->request_queue);
+		spin_lock_irqsave(shost->host_lock, flags);
+	
+		scsi_device_put(sdev);
+	}
+ out:
+	spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+/*
+ * Function:	scsi_run_queue()
+ *
+ * Purpose:	Select a proper request queue to serve next
+ *
+ * Arguments:	q	- last request's queue
+ *
+ * Returns:     Nothing
+ *
+ * Notes:	The previous command was completely finished, start
+ *		a new one if possible.
+ */
+static void scsi_run_queue(struct request_queue *q)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct Scsi_Host *shost = sdev->host;
+	unsigned long flags;
+
+	if (sdev->single_lun)
+		scsi_single_lun_run(sdev);
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	while (!list_empty(&shost->starved_list) &&
+	       !shost->host_blocked && !shost->host_self_blocked &&
+		!((shost->can_queue > 0) &&
+		  (shost->host_busy >= shost->can_queue))) {
+		/*
+		 * As long as shost is accepting commands and we have
+		 * starved queues, call blk_run_queue. scsi_request_fn
+		 * drops the queue_lock and can add us back to the
+		 * starved_list.
+		 *
+		 * host_lock protects the starved_list and starved_entry.
+		 * scsi_request_fn must get the host_lock before checking
+		 * or modifying starved_list or starved_entry.
+		 */
+		sdev = list_entry(shost->starved_list.next,
+					  struct scsi_device, starved_entry);
+		list_del_init(&sdev->starved_entry);
+		spin_unlock_irqrestore(shost->host_lock, flags);
+
+		blk_run_queue(sdev->request_queue);
+
+		spin_lock_irqsave(shost->host_lock, flags);
+		if (unlikely(!list_empty(&sdev->starved_entry)))
+			/*
+			 * sdev lost a race, and was put back on the
+			 * starved list. This is unlikely but without this
+			 * in theory we could loop forever.
+			 */
+			break;
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	blk_run_queue(q);
+}
+
+/*
  * Function:    scsi_insert_special_req()
  *
  * Purpose:     Insert pre-formed request into request queue.
@@ -92,7 +195,7 @@ int scsi_insert_special_req(struct scsi_
 	 */
 	sreq->sr_request->flags &= ~REQ_DONTPREP;
 	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
-		       	   at_head, sreq, 0);
+		       	   at_head, sreq);
 	return 0;
 }
 
@@ -119,6 +222,8 @@ int scsi_queue_insert(struct scsi_cmnd *
 {
 	struct Scsi_Host *host = cmd->device->host;
 	struct scsi_device *device = cmd->device;
+	struct request_queue *q = device->request_queue;
+	unsigned long flags;
 
 	SCSI_LOG_MLQUEUE(1,
 		 printk("Inserting command %p into mlqueue\n", cmd));
@@ -160,17 +265,17 @@ int scsi_queue_insert(struct scsi_cmnd *
 	scsi_device_unbusy(device);
 
 	/*
-	 * Insert this command at the head of the queue for it's device.
-	 * It will go before all other commands that are already in the queue.
-	 *
-	 * NOTE: there is magic here about the way the queue is plugged if
-	 * we have no outstanding commands.
-	 * 
-	 * Although this *doesn't* plug the queue, it does call the request
-	 * function.  The SCSI request function detects the blocked condition
-	 * and plugs the queue appropriately.
+	 * Requeue the command.  Turn on REQ_SOFTBARRIER to prevent
+	 * other requests from passing this request.
 	 */
-	blk_insert_request(device->request_queue, cmd->request, 1, cmd, 1);
+	cmd->request->flags |= REQ_SOFTBARRIER;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_requeue_request(q, cmd->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	scsi_run_queue(q);
+
 	return 0;
 }
 
@@ -355,109 +460,6 @@ void scsi_device_unbusy(struct scsi_devi
 }
 
 /*
- * Called for single_lun devices on IO completion. Clear starget_sdev_user,
- * and call blk_run_queue for all the scsi_devices on the target -
- * including current_sdev first.
- *
- * Called with *no* scsi locks held.
- */
-static void scsi_single_lun_run(struct scsi_device *current_sdev)
-{
-	struct Scsi_Host *shost = current_sdev->host;
-	struct scsi_device *sdev, *tmp;
-	struct scsi_target *starget = scsi_target(current_sdev);
-	unsigned long flags;
-
-	spin_lock_irqsave(shost->host_lock, flags);
-	starget->starget_sdev_user = NULL;
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
-	/*
-	 * Call blk_run_queue for all LUNs on the target, starting with
-	 * current_sdev. We race with others (to set starget_sdev_user),
-	 * but in most cases, we will be first. Ideally, each LU on the
-	 * target would get some limited time or requests on the target.
-	 */
-	blk_run_queue(current_sdev->request_queue);
-
-	spin_lock_irqsave(shost->host_lock, flags);
-	if (starget->starget_sdev_user)
-		goto out;
-	list_for_each_entry_safe(sdev, tmp, &starget->devices,
-			same_target_siblings) {
-		if (sdev == current_sdev)
-			continue;
-		if (scsi_device_get(sdev))
-			continue;
-
-		spin_unlock_irqrestore(shost->host_lock, flags);
-		blk_run_queue(sdev->request_queue);
-		spin_lock_irqsave(shost->host_lock, flags);
-	
-		scsi_device_put(sdev);
-	}
- out:
-	spin_unlock_irqrestore(shost->host_lock, flags);
-}
-
-/*
- * Function:	scsi_run_queue()
- *
- * Purpose:	Select a proper request queue to serve next
- *
- * Arguments:	q	- last request's queue
- *
- * Returns:     Nothing
- *
- * Notes:	The previous command was completely finished, start
- *		a new one if possible.
- */
-static void scsi_run_queue(struct request_queue *q)
-{
-	struct scsi_device *sdev = q->queuedata;
-	struct Scsi_Host *shost = sdev->host;
-	unsigned long flags;
-
-	if (sdev->single_lun)
-		scsi_single_lun_run(sdev);
-
-	spin_lock_irqsave(shost->host_lock, flags);
-	while (!list_empty(&shost->starved_list) &&
-	       !shost->host_blocked && !shost->host_self_blocked &&
-		!((shost->can_queue > 0) &&
-		  (shost->host_busy >= shost->can_queue))) {
-		/*
-		 * As long as shost is accepting commands and we have
-		 * starved queues, call blk_run_queue. scsi_request_fn
-		 * drops the queue_lock and can add us back to the
-		 * starved_list.
-		 *
-		 * host_lock protects the starved_list and starved_entry.
-		 * scsi_request_fn must get the host_lock before checking
-		 * or modifying starved_list or starved_entry.
-		 */
-		sdev = list_entry(shost->starved_list.next,
-					  struct scsi_device, starved_entry);
-		list_del_init(&sdev->starved_entry);
-		spin_unlock_irqrestore(shost->host_lock, flags);
-
-		blk_run_queue(sdev->request_queue);
-
-		spin_lock_irqsave(shost->host_lock, flags);
-		if (unlikely(!list_empty(&sdev->starved_entry)))
-			/*
-			 * sdev lost a race, and was put back on the
-			 * starved list. This is unlikely but without this
-			 * in theory we could loop forever.
-			 */
-			break;
-	}
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
-	blk_run_queue(q);
-}
-
-/*
  * Function:	scsi_requeue_command()
  *
  * Purpose:	Handle post-processing of completed commands.
@@ -476,8 +478,14 @@ static void scsi_run_queue(struct reques
  */
 static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
 {
+	unsigned long flags;
+
 	cmd->request->flags &= ~REQ_DONTPREP;
-	blk_insert_request(q, cmd->request, 1, cmd, 1);
+	cmd->request->flags |= REQ_SOFTBARRIER;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_requeue_request(q, cmd->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	scsi_run_queue(q);
 }
Index: scsi-export/include/linux/blkdev.h
===================================================================
--- scsi-export.orig/include/linux/blkdev.h	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/include/linux/blkdev.h	2005-03-31 18:06:19.000000000 +0900
@@ -541,7 +541,7 @@ extern void blk_end_sync_rq(struct reque
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
 extern void __blk_attempt_remerge(request_queue_t *, struct request *);
 extern struct request *blk_get_request(request_queue_t *, int, int);
-extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int);
+extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
 extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure.
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
  2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 17:53   ` James Bottomley
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 03/13] scsi: remove unused scsi_cmnd->internal_timeout field Tejun Heo
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

02_scsi_no_REQ_SPECIAL_on_sgtable_allocation_failure.patch

	Don't turn on REQ_SPECIAL on sgtable allocation failure.  This
	was the last place where REQ_SPECIAL is turned on for normal
	requests.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_lib.c |    4 +---
 1 files changed, 1 insertion(+), 3 deletions(-)

Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:19.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:20.000000000 +0900
@@ -940,10 +940,8 @@ static int scsi_init_io(struct scsi_cmnd
 	 * if sg table allocation fails, requeue request later.
 	 */
 	sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
-	if (unlikely(!sgpnt)) {
-		req->flags |= REQ_SPECIAL;
+	if (unlikely(!sgpnt))
 		return BLKPREP_DEFER;
-	}
 
 	cmd->request_buffer = (char *) sgpnt;
 	cmd->request_bufflen = req->nr_sectors << 9;


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 03/13] scsi: remove unused scsi_cmnd->internal_timeout field
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
  2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions Tejun Heo
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

03_scsi_remove_internal_timeout.patch

	scsi_cmnd->internal_timeout field doesn't have any meaning
	anymore.  Kill the field.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 drivers/scsi/advansys.c   |    2 --
 drivers/scsi/pci2000.c    |    4 ++--
 drivers/scsi/scsi.c       |    1 -
 drivers/scsi/scsi_error.c |    1 -
 drivers/scsi/scsi_lib.c   |    1 -
 drivers/scsi/scsi_priv.h  |    5 -----
 include/scsi/scsi_cmnd.h  |    6 ------
 7 files changed, 2 insertions(+), 18 deletions(-)

Index: scsi-export/drivers/scsi/advansys.c
===================================================================
--- scsi-export.orig/drivers/scsi/advansys.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/advansys.c	2005-03-31 18:06:20.000000000 +0900
@@ -9206,8 +9206,6 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
 " timeout_per_command %d, timeout_total %d, timeout %d\n",
         s->timeout_per_command, s->timeout_total, s->timeout);
 
-    printk(" internal_timeout %u\n", s->internal_timeout);
-
     printk(
 " scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n",
         (ulong) s->scsi_done, (ulong) s->done,
Index: scsi-export/drivers/scsi/pci2000.c
===================================================================
--- scsi-export.orig/drivers/scsi/pci2000.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/pci2000.c	2005-03-31 18:06:20.000000000 +0900
@@ -438,8 +438,8 @@ int Pci2000_QueueCommand (Scsi_Cmnd *SCp
 	if ( bus )
 		{
 		DEB (if(*cdb) printk ("\nCDB: %X-  %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
-		DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command,
-							  SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout));
+		DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
+							  SCpnt->timeout_total, SCpnt->timeout));
 		outl (SCpnt->timeout_per_command, padapter->mb1);
 		outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
 		if ( WaitReady (padapter) )
Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:20.000000000 +0900
@@ -716,7 +716,6 @@ void scsi_init_cmd_from_req(struct scsi_
 	/*
 	 * Start the timer ticking.
 	 */
-	cmd->internal_timeout = NORMAL_TIMEOUT;
 	cmd->abort_reason = 0;
 	cmd->result = 0;
 
Index: scsi-export/drivers/scsi/scsi_error.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_error.c	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_error.c	2005-03-31 18:06:20.000000000 +0900
@@ -1843,7 +1843,6 @@ scsi_reset_provider(struct scsi_device *
 	scmd->bufflen			= 0;
 	scmd->request_buffer		= NULL;
 	scmd->request_bufflen		= 0;
-	scmd->internal_timeout		= NORMAL_TIMEOUT;
 	scmd->abort_reason		= DID_ABORT;
 
 	scmd->cmd_len			= 0;
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:20.000000000 +0900
@@ -414,7 +414,6 @@ static int scsi_init_cmd_errh(struct scs
 	memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd));
 	cmd->buffer = cmd->request_buffer;
 	cmd->bufflen = cmd->request_bufflen;
-	cmd->internal_timeout = NORMAL_TIMEOUT;
 	cmd->abort_reason = 0;
 
 	return 1;
Index: scsi-export/drivers/scsi/scsi_priv.h
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_priv.h	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_priv.h	2005-03-31 18:06:20.000000000 +0900
@@ -30,11 +30,6 @@ struct Scsi_Host;
 #define SCSI_REQ_MAGIC		0x75F6D354
 
 /*
- *  Flag bit for the internal_timeout array
- */
-#define NORMAL_TIMEOUT		0
-
-/*
  * Scsi Error Handler Flags
  */
 #define scsi_eh_eflags_chk(scp, flags) \
Index: scsi-export/include/scsi/scsi_cmnd.h
===================================================================
--- scsi-export.orig/include/scsi/scsi_cmnd.h	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/include/scsi/scsi_cmnd.h	2005-03-31 18:06:20.000000000 +0900
@@ -65,12 +65,6 @@ struct scsi_cmnd {
 	int timeout_total;
 	int timeout;
 
-	/*
-	 * We handle the timeout differently if it happens when a reset, 
-	 * abort, etc are in process. 
-	 */
-	unsigned volatile char internal_timeout;
-
 	unsigned char cmd_len;
 	unsigned char old_cmd_len;
 	enum dma_data_direction sc_data_direction;


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (2 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 03/13] scsi: remove unused scsi_cmnd->internal_timeout field Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 10:11   ` Christoph Hellwig
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer Tejun Heo
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

04_scsi_remove_volatile.patch

	scsi_device->device_busy, Scsi_Host->host_busy and
	->host_failed have volatile qualifiers, but the qualifiers
	don't serve any purpose.  Kill them.  While at it, protect
	->host_failed update in scsi_error for consistency and clarity.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_device.h |    3 ++-
 scsi_host.h   |   10 ++++++++--
 2 files changed, 10 insertions(+), 3 deletions(-)

Index: scsi-export/include/scsi/scsi_device.h
===================================================================
--- scsi-export.orig/include/scsi/scsi_device.h	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/include/scsi/scsi_device.h	2005-03-31 18:06:20.000000000 +0900
@@ -43,7 +43,8 @@ struct scsi_device {
 	struct list_head    siblings;   /* list of all devices on this host */
 	struct list_head    same_target_siblings; /* just the devices sharing same target id */
 
-	volatile unsigned short device_busy;	/* commands actually active on low-level */
+	unsigned short device_busy;	/* commands actually active on
+					 * low-level. protected by sdev_lock. */
 	spinlock_t sdev_lock;           /* also the request queue_lock */
 	spinlock_t list_lock;
 	struct list_head cmd_list;	/* queue of in use SCSI Command structures */
Index: scsi-export/include/scsi/scsi_host.h
===================================================================
--- scsi-export.orig/include/scsi/scsi_host.h	2005-03-31 17:42:05.000000000 +0900
+++ scsi-export/include/scsi/scsi_host.h	2005-03-31 18:06:20.000000000 +0900
@@ -448,8 +448,14 @@ struct Scsi_Host {
 	wait_queue_head_t       host_wait;
 	struct scsi_host_template *hostt;
 	struct scsi_transport_template *transportt;
-	volatile unsigned short host_busy;   /* commands actually active on low-level */
-	volatile unsigned short host_failed; /* commands that failed. */
+
+	/*
+	 * The following two fields are protected with host_lock;
+	 * however, eh routines can safely access during eh processing
+	 * without acquiring the lock.
+	 */
+	unsigned short host_busy;	   /* commands actually active on low-level */
+	unsigned short host_failed;	   /* commands that failed. */
     
 	unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
 	int resetting; /* if set, it means that last_reset is a valid value */


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (3 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 10:13   ` Christoph Hellwig
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 06/13] scsi: remove meaningless scsi_cmnd->serial_number_at_timeout field Tejun Heo
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

05_scsi_timer_cleanup.patch

	scsi_queue_insert() has four callers.  Three callers call with
	timer disabled and one (the second invocation in
	scsi_dispatch_cmd()) calls with timer activated.
	scsi_queue_insert() used to always call scsi_delete_timer()
	and ignore the return value.  This results in race with timer
	expiration.  Remove scsi_delete_timer() call from
	scsi_queue_insert() and make the caller delete timer and check
	the return value.

	While at it, as, once a scsi timer is added, it should expire
	or be deleted before reused, make scsi_add_timer() strict
	about timer reuses.  Now timer expiration function should
	clear ->function and all timer deletion should go through
	scsi_delete_timer().  Also, remove bogus ->eh_action tests
	from scsi_eh_{done|times_out} functions.  The condition is
	always true and the test is somewhat misleading.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 aic7xxx/aic79xx_osm.c |    1 +
 aic7xxx/aic7xxx_osm.c |    1 +
 scsi.c                |   10 ++++++----
 scsi_error.c          |   25 ++++++++-----------------
 scsi_lib.c            |    6 ------
 5 files changed, 16 insertions(+), 27 deletions(-)

Index: scsi-export/drivers/scsi/aic7xxx/aic79xx_osm.c
===================================================================
--- scsi-export.orig/drivers/scsi/aic7xxx/aic79xx_osm.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/aic7xxx/aic79xx_osm.c	2005-03-31 18:06:21.000000000 +0900
@@ -2725,6 +2725,7 @@ ahd_linux_dv_target(struct ahd_softc *ah
 		/* Queue the command and wait for it to complete */
 		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
 		init_timer(&cmd->eh_timeout);
+		cmd->eh_timeout.function = NULL;
 #ifdef AHD_DEBUG
 		if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
 			/*
Index: scsi-export/drivers/scsi/aic7xxx/aic7xxx_osm.c
===================================================================
--- scsi-export.orig/drivers/scsi/aic7xxx/aic7xxx_osm.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/aic7xxx/aic7xxx_osm.c	2005-03-31 18:06:21.000000000 +0900
@@ -2409,6 +2409,7 @@ ahc_linux_dv_target(struct ahc_softc *ah
 		/* Queue the command and wait for it to complete */
 		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
 		init_timer(&cmd->eh_timeout);
+		cmd->eh_timeout.function = NULL;
 #ifdef AHC_DEBUG
 		if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
 			/*
Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:21.000000000 +0900
@@ -638,10 +638,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 	}
 	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
-		atomic_inc(&cmd->device->iodone_cnt);
-		scsi_queue_insert(cmd,
-				(rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
-				 rtn : SCSI_MLQUEUE_HOST_BUSY);
+		if (scsi_delete_timer(cmd)) {
+			atomic_inc(&cmd->device->iodone_cnt);
+			scsi_queue_insert(cmd,
+					  (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
+					  rtn : SCSI_MLQUEUE_HOST_BUSY);
+		}
 		SCSI_LOG_MLQUEUE(3,
 		    printk("queuecommand : request rejected\n"));
 	}
Index: scsi-export/drivers/scsi/scsi_error.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_error.c	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_error.c	2005-03-31 18:06:21.000000000 +0900
@@ -107,14 +107,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *s
 void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
 		    void (*complete)(struct scsi_cmnd *))
 {
-
-	/*
-	 * If the clock was already running for this command, then
-	 * first delete the timer.  The timer handling code gets rather
-	 * confused if we don't do this.
-	 */
-	if (scmd->eh_timeout.function)
-		del_timer(&scmd->eh_timeout);
+	BUG_ON(scmd->eh_timeout.function);
 
 	scmd->eh_timeout.data = (unsigned long)scmd;
 	scmd->eh_timeout.expires = jiffies + timeout;
@@ -168,6 +161,8 @@ EXPORT_SYMBOL(scsi_delete_timer);
  **/
 void scsi_times_out(struct scsi_cmnd *scmd)
 {
+	scmd->eh_timeout.function = NULL;
+
 	scsi_log_completion(scmd, TIMEOUT_ERROR);
 
 	if (scmd->device->host->hostt->eh_timed_out)
@@ -439,12 +434,12 @@ static int scsi_eh_completed_normally(st
  **/
 static void scsi_eh_times_out(struct scsi_cmnd *scmd)
 {
+	scmd->eh_timeout.function = NULL;
+
 	scsi_eh_eflags_set(scmd, SCSI_EH_REC_TIMEOUT);
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd:%p\n", __FUNCTION__,
 					  scmd));
-
-	if (scmd->device->host->eh_action)
-		up(scmd->device->host->eh_action);
+	up(scmd->device->host->eh_action);
 }
 
 /**
@@ -459,15 +454,12 @@ static void scsi_eh_done(struct scsi_cmn
 	 * way of stopping the timeout handler from running, so we must
 	 * always defer to it.
 	 */
-	if (del_timer(&scmd->eh_timeout)) {
+	if (scsi_delete_timer(scmd)) {
 		scmd->request->rq_status = RQ_SCSI_DONE;
 		scmd->owner = SCSI_OWNER_ERROR_HANDLER;
-
 		SCSI_LOG_ERROR_RECOVERY(3, printk("%s scmd: %p result: %x\n",
 					   __FUNCTION__, scmd, scmd->result));
-
-		if (scmd->device->host->eh_action)
-			up(scmd->device->host->eh_action);
+		up(scmd->device->host->eh_action);
 	}
 }
 
@@ -1877,7 +1869,6 @@ scsi_reset_provider(struct scsi_device *
 		rtn = FAILED;
 	}
 
-	scsi_delete_timer(scmd);
 	scsi_next_command(scmd);
 	return rtn;
 }
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
@@ -229,12 +229,6 @@ int scsi_queue_insert(struct scsi_cmnd *
 		 printk("Inserting command %p into mlqueue\n", cmd));
 
 	/*
-	 * We are inserting the command into the ml queue.  First, we
-	 * cancel the timer, so it doesn't time out.
-	 */
-	scsi_delete_timer(cmd);
-
-	/*
 	 * Next, set the appropriate busy bit for the device/host.
 	 *
 	 * If the host/device isn't busy, assume that something actually


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 06/13] scsi: remove meaningless scsi_cmnd->serial_number_at_timeout field
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (4 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn() Tejun Heo
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

06_scsi_remove_serial_number_at_timeout.patch

	scsi_cmnd->serial_number_at_timeout doesn't serve any purpose
	anymore.  All serial_number == serial_number_at_timeout tests
	are always true in abort callbacks.  Kill the field.  Also, as
	->pid always equals ->serial_number and ->serial_number
	doesn't have any special meaning anymore, update comments
	above ->serial_number accordingly.  Once we remove all uses of
	this field from all lldd's, this field should go.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 drivers/scsi/BusLogic.c             |    7 -------
 drivers/scsi/advansys.c             |    5 ++---
 drivers/scsi/ips.c                  |    7 -------
 drivers/scsi/ncr53c8xx.c            |   14 ++------------
 drivers/scsi/qla2xxx/qla_dbg.c      |    6 ++----
 drivers/scsi/scsi.c                 |    2 --
 drivers/scsi/scsi_error.c           |    7 -------
 drivers/scsi/scsi_lib.c             |    1 -
 drivers/scsi/sym53c8xx_2/sym_glue.c |    6 ------
 include/scsi/scsi_cmnd.h            |   22 +++++++++-------------
 10 files changed, 15 insertions(+), 62 deletions(-)

Index: scsi-export/drivers/scsi/BusLogic.c
===================================================================
--- scsi-export.orig/drivers/scsi/BusLogic.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/BusLogic.c	2005-03-31 18:06:21.000000000 +0900
@@ -2958,13 +2958,6 @@ static int BusLogic_AbortCommand(struct 
 	struct BusLogic_CCB *CCB;
 	BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
 	/*
-	   If this Command has already completed, then no Abort is necessary.
-	 */
-	if (Command->serial_number != Command->serial_number_at_timeout) {
-		BusLogic_Warning("Unable to Abort Command to Target %d - " "Already Completed\n", HostAdapter, TargetID);
-		return SUCCESS;
-	}
-	/*
 	   Attempt to find an Active CCB for this Command.  If no Active CCB for this
 	   Command is found, then no Abort is necessary.
 	 */
Index: scsi-export/drivers/scsi/advansys.c
===================================================================
--- scsi-export.orig/drivers/scsi/advansys.c	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/advansys.c	2005-03-31 18:06:21.000000000 +0900
@@ -9198,9 +9198,8 @@ asc_prt_scsi_cmnd(struct scsi_cmnd *s)
         s->use_sg, s->sglist_len, s->abort_reason);
 
     printk(
-" serial_number 0x%x, serial_number_at_timeout 0x%x, retries %d, allowed %d\n",
-        (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
-         s->retries, s->allowed);
+" serial_number 0x%x, retries %d, allowed %d\n",
+        (unsigned) s->serial_number, s->retries, s->allowed);
 
     printk(
 " timeout_per_command %d, timeout_total %d, timeout %d\n",
Index: scsi-export/drivers/scsi/ips.c
===================================================================
--- scsi-export.orig/drivers/scsi/ips.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/ips.c	2005-03-31 18:06:21.000000000 +0900
@@ -833,13 +833,6 @@ ips_eh_abort(Scsi_Cmnd * SC)
 	if (!ha->active)
 		return (FAILED);
 
-	if (SC->serial_number != SC->serial_number_at_timeout) {
-		/* HMM, looks like a bogus command */
-		DEBUG(1, "Abort called with bogus scsi command");
-
-		return (FAILED);
-	}
-
 	/* See if the command is on the copp queue */
 	item = ha->copp_waitlist.head;
 	while ((item) && (item->scsi_cmd != SC))
Index: scsi-export/drivers/scsi/ncr53c8xx.c
===================================================================
--- scsi-export.orig/drivers/scsi/ncr53c8xx.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/ncr53c8xx.c	2005-03-31 18:06:21.000000000 +0900
@@ -7601,24 +7601,14 @@ static int ncr53c8xx_abort(struct scsi_c
 	struct scsi_cmnd *done_list;
 
 #if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
-	printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n",
-		cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout);
+	printk("ncr53c8xx_abort: pid=%lu serial_number=%ld\n",
+		cmd->pid, cmd->serial_number);
 #else
 	printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid);
 #endif
 
 	NCR_LOCK_NCB(np, flags);
 
-#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
-	/*
-	 * We have to just ignore abort requests in some situations.
-	 */
-	if (cmd->serial_number != cmd->serial_number_at_timeout) {
-		sts = SCSI_ABORT_NOT_RUNNING;
-		goto out;
-	}
-#endif
-
 	sts = ncr_abort_command(np, cmd);
 out:
 	done_list     = np->done_list;
Index: scsi-export/drivers/scsi/qla2xxx/qla_dbg.c
===================================================================
--- scsi-export.orig/drivers/scsi/qla2xxx/qla_dbg.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/qla2xxx/qla_dbg.c	2005-03-31 18:06:21.000000000 +0900
@@ -1050,10 +1050,8 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd 
 	for (i = 0; i < cmd->cmd_len; i++) {
 		printk("0x%02x ", cmd->cmnd[i]);
 	}
-	printk("\n  seg_cnt=%d, allowed=%d, retries=%d, "
-	    "serial_number_at_timeout=0x%lx\n",
-	    cmd->use_sg, cmd->allowed, cmd->retries,
-	    cmd->serial_number_at_timeout);
+	printk("\n  seg_cnt=%d, allowed=%d, retries=%d\n",
+	    cmd->use_sg, cmd->allowed, cmd->retries);
 	printk("  request buffer=0x%p, request buffer len=0x%x\n",
 	    cmd->request_buffer, cmd->request_bufflen);
 	printk("  tag=%d, transfersize=0x%x\n",
Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:21.000000000 +0900
@@ -688,7 +688,6 @@ void scsi_init_cmd_from_req(struct scsi_
 	cmd->request = sreq->sr_request;
 	memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd));
 	cmd->serial_number = 0;
-	cmd->serial_number_at_timeout = 0;
 	cmd->bufflen = sreq->sr_bufflen;
 	cmd->buffer = sreq->sr_buffer;
 	cmd->retries = 0;
@@ -767,7 +766,6 @@ void __scsi_done(struct scsi_cmnd *cmd)
 	 * Set the serial numbers back to zero
 	 */
 	cmd->serial_number = 0;
-	cmd->serial_number_at_timeout = 0;
 	cmd->state = SCSI_STATE_BHQUEUE;
 	cmd->owner = SCSI_OWNER_BH_HANDLER;
 
Index: scsi-export/drivers/scsi/scsi_error.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_error.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_error.c	2005-03-31 18:06:21.000000000 +0900
@@ -80,11 +80,6 @@ int scsi_eh_scmd_add(struct scsi_cmnd *s
 	 */
 	scmd->owner = SCSI_OWNER_ERROR_HANDLER;
 	scmd->state = SCSI_STATE_FAILED;
-	/*
-	 * Set the serial_number_at_timeout to the current
-	 * serial_number
-	 */
-	scmd->serial_number_at_timeout = scmd->serial_number;
 	list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
 	set_bit(SHOST_RECOVERY, &shost->shost_state);
 	shost->host_failed++;
@@ -1057,7 +1052,6 @@ static int scsi_try_bus_reset(struct scs
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
 					  __FUNCTION__));
 	scmd->owner = SCSI_OWNER_LOWLEVEL;
-	scmd->serial_number_at_timeout = scmd->serial_number;
 
 	if (!scmd->device->host->hostt->eh_bus_reset_handler)
 		return FAILED;
@@ -1089,7 +1083,6 @@ static int scsi_try_host_reset(struct sc
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
 					  __FUNCTION__));
 	scmd->owner = SCSI_OWNER_LOWLEVEL;
-	scmd->serial_number_at_timeout = scmd->serial_number;
 
 	if (!scmd->device->host->hostt->eh_host_reset_handler)
 		return FAILED;
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
@@ -386,7 +386,6 @@ static int scsi_init_cmd_errh(struct scs
 {
 	cmd->owner = SCSI_OWNER_MIDLEVEL;
 	cmd->serial_number = 0;
-	cmd->serial_number_at_timeout = 0;
 	cmd->abort_reason = 0;
 
 	memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
Index: scsi-export/drivers/scsi/sym53c8xx_2/sym_glue.c
===================================================================
--- scsi-export.orig/drivers/scsi/sym53c8xx_2/sym_glue.c	2005-03-31 17:42:04.000000000 +0900
+++ scsi-export/drivers/scsi/sym53c8xx_2/sym_glue.c	2005-03-31 18:06:21.000000000 +0900
@@ -799,12 +799,6 @@ static int sym_eh_handler(int op, char *
 
 	dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
 
-#if 0
-	/* This one should be the result of some race, thus to ignore */
-	if (cmd->serial_number != cmd->serial_number_at_timeout)
-		goto prepare;
-#endif
-
 	/* This one is queued in some place -> to wait for completion */
 	FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
 		struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
Index: scsi-export/include/scsi/scsi_cmnd.h
===================================================================
--- scsi-export.orig/include/scsi/scsi_cmnd.h	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/include/scsi/scsi_cmnd.h	2005-03-31 18:06:21.000000000 +0900
@@ -43,21 +43,17 @@ struct scsi_cmnd {
 	void (*done) (struct scsi_cmnd *);	/* Mid-level done function */
 
 	/*
-	 * A SCSI Command is assigned a nonzero serial_number when internal_cmnd
-	 * passes it to the driver's queue command function.  The serial_number
-	 * is cleared when scsi_done is entered indicating that the command has
-	 * been completed.  If a timeout occurs, the serial number at the moment
-	 * of timeout is copied into serial_number_at_timeout.  By subsequently
-	 * comparing the serial_number and serial_number_at_timeout fields
-	 * during abort or reset processing, we can detect whether the command
-	 * has already completed.  This also detects cases where the command has
-	 * completed and the SCSI Command structure has already being reused
-	 * for another command, so that we can avoid incorrectly aborting or
-	 * resetting the new command.
-	 * The serial number is only unique per host.
+	 * A SCSI Command is assigned a nonzero serial_number before passed
+	 * to the driver's queue command function.  The serial_number is
+	 * cleared when scsi_done is entered indicating that the command
+	 * has been completed.  It currently doesn't have much use other
+	 * than printk's.  Some lldd's use this number for other purposes.
+	 * It's almost certain that such usages are either incorrect or
+	 * meaningless.  Please kill all usages other than printk's.  Also,
+	 * as this number is always identical to ->pid, please convert
+	 * printk's to use ->pid, so that we can kill this field.
 	 */
 	unsigned long serial_number;
-	unsigned long serial_number_at_timeout;
 
 	int retries;
 	int allowed;


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn()
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (5 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 06/13] scsi: remove meaningless scsi_cmnd->serial_number_at_timeout field Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-04-01 18:23   ` James Bottomley
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn() Tejun Heo
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

07_scsi_consolidate_prep_fn_error_handling.patch

	When scsi_init_io() returns BLKPREP_DEFER or BLKPREP_KILL,
	it's supposed to free resources itself.  This patch
	consolidates defer and kill handling into scsi_prep_fn().
	This fixes a queue stall bug which occurred when sgtable
	allocation failed and device_busy == 0.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_lib.c |   23 ++++++++++++-----------
 1 files changed, 12 insertions(+), 11 deletions(-)

Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
@@ -960,9 +960,6 @@ static int scsi_init_io(struct scsi_cmnd
 	printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
 			req->current_nr_sectors);
 
-	/* release the command and kill it */
-	scsi_release_buffers(cmd);
-	scsi_put_command(cmd);
 	return BLKPREP_KILL;
 }
 
@@ -1130,18 +1127,17 @@ static int scsi_prep_fn(struct request_q
 		 * required).
 		 */
 		ret = scsi_init_io(cmd);
-		if (ret)	/* BLKPREP_KILL return also releases the command */
-			return ret;
-		
+		if (ret == BLKPREP_DEFER)
+			goto defer;
+		else if (ret == BLKPREP_KILL)
+			goto kill;
+
 		/*
 		 * Initialize the actual SCSI command for this request.
 		 */
 		drv = *(struct scsi_driver **)req->rq_disk->private_data;
-		if (unlikely(!drv->init_command(cmd))) {
-			scsi_release_buffers(cmd);
-			scsi_put_command(cmd);
-			return BLKPREP_KILL;
-		}
+		if (unlikely(!drv->init_command(cmd)))
+			goto kill;
 	}
 
 	/*
@@ -1157,6 +1153,11 @@ static int scsi_prep_fn(struct request_q
 	if (sdev->device_busy == 0)
 		blk_plug_device(q);
 	return BLKPREP_DEFER;
+
+ kill:
+	scsi_release_buffers(cmd);
+	scsi_put_command(cmd);
+	return BLKPREP_KILL;
 }
 
 /*


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (6 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn() Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 10:20   ` Christoph Hellwig
  2005-03-31 18:07   ` James Bottomley
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up Tejun Heo
                   ` (4 subsequent siblings)
  12 siblings, 2 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

08_scsi_move_preps_to_prep_fn.patch

	Move request preparations scattered in scsi_request_fn() and
	scsi_dispatch_cmd() into scsi_prep_fn().

	* CDB_SIZE check in scsi_dispatch_cmd()
	* SCSI-2 LUN preparation in scsi_dispatch_cmd()
	* scsi_init_cmd_errh() in scsi_request_fn()

	No invalid request reaches scsi_request_fn() anymore.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi.c     |   30 ------------------------------
 scsi_lib.c |   25 +++++++++++++++++++------
 2 files changed, 19 insertions(+), 36 deletions(-)

Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:22.000000000 +0900
@@ -79,15 +79,6 @@
 #define MIN_RESET_PERIOD (15*HZ)
 
 /*
- * Macro to determine the size of SCSI command. This macro takes vendor
- * unique commands into account. SCSI commands in groups 6 and 7 are
- * vendor unique and we will depend upon the command length being
- * supplied correctly in cmd_len.
- */
-#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
-				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -566,14 +557,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 		goto out;
 	}
 
-	/* 
-	 * If SCSI-2 or lower, store the LUN value in cmnd.
-	 */
-	if (cmd->device->scsi_level <= SCSI_2) {
-		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
-			       (cmd->device->lun << 5 & 0xe0);
-	}
-
 	/*
 	 * We will wait MIN_RESET_DELAY clock ticks after the last reset so
 	 * we can avoid the drive not being ready.
@@ -614,19 +597,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
 
 	atomic_inc(&cmd->device->iorequest_cnt);
 
-	/*
-	 * Before we queue this command, check if the command
-	 * length exceeds what the host adapter can handle.
-	 */
-	if (CDB_SIZE(cmd) > cmd->device->host->max_cmd_len) {
-		SCSI_LOG_MLQUEUE(3,
-				printk("queuecommand : command too long.\n"));
-		cmd->result = (DID_ABORT << 16);
-
-		scsi_done(cmd);
-		goto out;
-	}
-
 	spin_lock_irqsave(host->host_lock, flags);
 	scsi_cmd_get_serial(host, cmd); 
 
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
@@ -28,6 +28,14 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
+/*
+ * Macro to determine the size of SCSI command. This macro takes vendor
+ * unique commands into account. SCSI commands in groups 6 and 7 are
+ * vendor unique and we will depend upon the command length being
+ * supplied correctly in cmd_len.
+ */
+#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
+				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
 
 #define SG_MEMPOOL_NR		(sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool))
 #define SG_MEMPOOL_SIZE		32
@@ -1140,6 +1148,17 @@ static int scsi_prep_fn(struct request_q
 			goto kill;
 	}
 
+	/* Check command length. */
+	if (CDB_SIZE(cmd) > sdev->host->max_cmd_len)
+		goto kill;
+
+	scsi_init_cmd_errh(cmd);
+
+	/* If SCSI-2 or lower, store the LUN value in cmnd. */
+	if (cmd->device->scsi_level <= SCSI_2)
+		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
+			(cmd->device->lun << 5 & 0xe0);
+
 	/*
 	 * The request is now prepped, no need to come back here
 	 */
@@ -1316,12 +1335,6 @@ static void scsi_request_fn(struct reque
 		}
 
 		/*
-		 * Finally, initialize any error handling parameters, and set up
-		 * the timers for timeouts.
-		 */
-		scsi_init_cmd_errh(cmd);
-
-		/*
 		 * Dispatch the command to the low-level driver.
 		 */
 		rtn = scsi_dispatch_cmd(cmd);


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (7 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn() Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 10:22   ` Christoph Hellwig
  2005-03-31 18:02   ` James Bottomley
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn() Tejun Heo
                   ` (3 subsequent siblings)
  12 siblings, 2 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

09_scsi_prep_fn_comment_update.patch

	Remove bogus comments from scsi_prep_fn() and clean up a bit.
	While at it, remove leading and tailing empty comment lines
	for one or two liners to make the code more concise.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_lib.c |   35 ++++++++---------------------------
 1 files changed, 8 insertions(+), 27 deletions(-)

Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
@@ -1051,14 +1051,11 @@ static int scsi_prep_fn(struct request_q
 	}
 
 	/*
-	 * Find the actual device driver associated with this command.
 	 * The SPECIAL requests are things like character device or
 	 * ioctls, which did not originate from ll_rw_blk.  Note that
 	 * the special field is also used to indicate the cmd for
 	 * the remainder of a partially fulfilled request that can 
-	 * come up when there is a medium error.  We have to treat
-	 * these two cases differently.  We differentiate by looking
-	 * at request->cmd, as this tells us the real story.
+	 * come up when there is a medium error.
 	 */
 	if (req->flags & REQ_SPECIAL) {
 		struct scsi_request *sreq = req->special;
@@ -1099,26 +1096,16 @@ static int scsi_prep_fn(struct request_q
 		blk_dump_rq_flags(req, "SCSI bad req");
 		return BLKPREP_KILL;
 	}
-	
-	/* note the overloading of req->special.  When the tag
-	 * is active it always means cmd.  If the tag goes
-	 * back for re-queueing, it may be reset */
+
 	req->special = cmd;
 	cmd->request = req;
-	
-	/*
-	 * FIXME: drop the lock here because the functions below
-	 * expect to be called without the queue lock held.  Also,
-	 * previously, we dequeued the request before dropping the
-	 * lock.  We hope REQ_STARTED prevents anything untoward from
-	 * happening now.
-	 */
+
 	if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 		struct scsi_driver *drv;
 		int ret;
 
 		/*
-		 * This will do a couple of things:
+		 * drv->init_command will do a couple of things:
 		 *  1) Fill in the actual SCSI command.
 		 *  2) Fill in any other upper-level specific fields
 		 * (timeout).
@@ -1130,19 +1117,15 @@ static int scsi_prep_fn(struct request_q
 		 * request to be rejected immediately.
 		 */
 
-		/* 
-		 * This sets up the scatter-gather table (allocating if
-		 * required).
-		 */
+		/* This sets up the scatter-gather table (allocating if
+		 * required). */
 		ret = scsi_init_io(cmd);
 		if (ret == BLKPREP_DEFER)
 			goto defer;
 		else if (ret == BLKPREP_KILL)
 			goto kill;
 
-		/*
-		 * Initialize the actual SCSI command for this request.
-		 */
+		/* Initialize the actual SCSI command for this request. */
 		drv = *(struct scsi_driver **)req->rq_disk->private_data;
 		if (unlikely(!drv->init_command(cmd)))
 			goto kill;
@@ -1159,9 +1142,7 @@ static int scsi_prep_fn(struct request_q
 		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
 			(cmd->device->lun << 5 & 0xe0);
 
-	/*
-	 * The request is now prepped, no need to come back here
-	 */
+	/* The request is now prepped, no need to come back here. */
 	req->flags |= REQ_DONTPREP;
 	return BLKPREP_OK;
 


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn()
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (8 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 11:14   ` Christoph Hellwig
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public Tejun Heo
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

10_scsi_request_fn_rewrite.patch

	This patch rewrites scsi_request_fn().  scsi_dispatch_cmd() is
	merged into scsi_request_fn().  Goals are

	* Remove unnecessary operations (host_lock unlocking/locking,
	  recursing into scsi_run_queue(), ...)
	* Consolidate defer/kill paths.
	* Be concise.

	The following changes fix bugs.

	* All killed requests now get fully prep'ed and pass through
	  __scsi_done().  This is the only kill path.
		- scsi_cmnd leak in offline-kill path removed
		- unfinished request bug in
		  scsi_dispatch_cmd():SDEV_DEL-kill path removed.
		- commands are never terminated directly from blk
		  layer unless they are invalid, so no need to supply
		  req->end_io callback for special requests.
	* Timer is added while holding host_lock, after all conditions
	  are checked and serial number is assigned.  This guarantees
	  that until host_lock is released, the scsi_cmnd pointed to
	  by cmd isn't released.  That didn't hold in the original
	  code and, theoretically, the original code could access
	  already released cmd.
	* For the same reason, if shost->hostt->queuecommand() fails,
	  we try to delete the timer before releasing host_lock.

	Other changes/notes

	* host_lock is acquired and released only once.
	  enter (qlocked) -> enter loop -> dev-prep -> switch to hlock -\
	                  ^---- switch to qlock <- issue <- host-prep <-/
	* unnecessary if () on get_device() removed.
	* loop on elv_next_request() instead of blk_queue_plugged().
	  We now explicitly break out of loop when we plug and check if
	  the queue has been plugged underneath us at the end of loop.
	* All device/host state checks are done in this function and
	  done only once while holding qlock/host_lock respectively.
	* Requests which get deferred during dev-prep are never
	  removed from request queue, so deferring is achieved by
	  simply breaking out of the loop and returning.
	* Failure of blk_queue_start_tag() on tagged queue is a BUG
	  now.  This condition should have been catched by
	  scsi_dev_queue_ready().
	* req->special == NULL test removed.  This just can't happen,
	  and even if it ever happens, scsi_request_fn() will
	  deterministically oops.
	* Requests which gets deferred during host-prep are requeued
	  using blk_requeue_request().  This is the only requeue path.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi.c     |  137 ------------------------------
 scsi_lib.c |  277 +++++++++++++++++++++++++++++++++----------------------------
 2 files changed, 153 insertions(+), 261 deletions(-)

Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:22.000000000 +0900
@@ -70,15 +70,6 @@
 
 
 /*
- * Definitions and constants.
- */
-
-#define MIN_RESET_DELAY (2*HZ)
-
-/* Do not call reset on error if we just did a reset within 15 sec. */
-#define MIN_RESET_PERIOD (15*HZ)
-
-/*
  * Note - the initial logging level can be set here to log events at boot time.
  * After the system is up, you may enable logging via the /proc interface.
  */
@@ -495,134 +486,6 @@ void scsi_log_completion(struct scsi_cmn
 }
 #endif
 
-/* 
- * Assign a serial number and pid to the request for error recovery
- * and debugging purposes.  Protected by the Host_Lock of host.
- */
-static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
-{
-	cmd->serial_number = host->cmd_serial_number++;
-	if (cmd->serial_number == 0) 
-		cmd->serial_number = host->cmd_serial_number++;
-	
-	cmd->pid = host->cmd_pid++;
-	if (cmd->pid == 0)
-		cmd->pid = host->cmd_pid++;
-}
-
-/*
- * Function:    scsi_dispatch_command
- *
- * Purpose:     Dispatch a command to the low-level driver.
- *
- * Arguments:   cmd - command block we are dispatching.
- *
- * Notes:
- */
-int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
-{
-	struct Scsi_Host *host = cmd->device->host;
-	unsigned long flags = 0;
-	unsigned long timeout;
-	int rtn = 0;
-
-	/* check if the device is still usable */
-	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
-		/* in SDEV_DEL we error all commands. DID_NO_CONNECT
-		 * returns an immediate error upwards, and signals
-		 * that the device is no longer present */
-		cmd->result = DID_NO_CONNECT << 16;
-		atomic_inc(&cmd->device->iorequest_cnt);
-		scsi_done(cmd);
-		/* return 0 (because the command has been processed) */
-		goto out;
-	}
-
-	/* Check to see if the scsi lld put this device into state SDEV_BLOCK. */
-	if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {
-		/* 
-		 * in SDEV_BLOCK, the command is just put back on the device
-		 * queue.  The suspend state has already blocked the queue so
-		 * future requests should not occur until the device 
-		 * transitions out of the suspend state.
-		 */
-		scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
-
-		SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n"));
-
-		/*
-		 * NOTE: rtn is still zero here because we don't need the
-		 * queue to be plugged on return (it's already stopped)
-		 */
-		goto out;
-	}
-
-	/*
-	 * We will wait MIN_RESET_DELAY clock ticks after the last reset so
-	 * we can avoid the drive not being ready.
-	 */
-	timeout = host->last_reset + MIN_RESET_DELAY;
-
-	if (host->resetting && time_before(jiffies, timeout)) {
-		int ticks_remaining = timeout - jiffies;
-		/*
-		 * NOTE: This may be executed from within an interrupt
-		 * handler!  This is bad, but for now, it'll do.  The irq
-		 * level of the interrupt handler has been masked out by the
-		 * platform dependent interrupt handling code already, so the
-		 * sti() here will not cause another call to the SCSI host's
-		 * interrupt handler (assuming there is one irq-level per
-		 * host).
-		 */
-		while (--ticks_remaining >= 0)
-			mdelay(1 + 999 / HZ);
-		host->resetting = 0;
-	}
-
-	/* 
-	 * AK: unlikely race here: for some reason the timer could
-	 * expire before the serial number is set up below.
-	 */
-	scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);
-
-	scsi_log_send(cmd);
-
-	/*
-	 * We will use a queued command if possible, otherwise we will
-	 * emulate the queuing and calling of completion function ourselves.
-	 */
-
-	cmd->state = SCSI_STATE_QUEUED;
-	cmd->owner = SCSI_OWNER_LOWLEVEL;
-
-	atomic_inc(&cmd->device->iorequest_cnt);
-
-	spin_lock_irqsave(host->host_lock, flags);
-	scsi_cmd_get_serial(host, cmd); 
-
-	if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
-		cmd->result = (DID_NO_CONNECT << 16);
-		scsi_done(cmd);
-	} else {
-		rtn = host->hostt->queuecommand(cmd, scsi_done);
-	}
-	spin_unlock_irqrestore(host->host_lock, flags);
-	if (rtn) {
-		if (scsi_delete_timer(cmd)) {
-			atomic_inc(&cmd->device->iodone_cnt);
-			scsi_queue_insert(cmd,
-					  (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
-					  rtn : SCSI_MLQUEUE_HOST_BUSY);
-		}
-		SCSI_LOG_MLQUEUE(3,
-		    printk("queuecommand : request rejected\n"));
-	}
-
- out:
-	SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n"));
-	return rtn;
-}
-
 /*
  * Function:    scsi_init_cmd_from_req
  *
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
@@ -28,6 +28,8 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
+#define MIN_RESET_DELAY (2*HZ)
+
 /*
  * Macro to determine the size of SCSI command. This macro takes vendor
  * unique commands into account. SCSI commands in groups 6 and 7 are
@@ -1023,32 +1025,6 @@ static int scsi_prep_fn(struct request_q
 {
 	struct scsi_device *sdev = q->queuedata;
 	struct scsi_cmnd *cmd;
-	int specials_only = 0;
-
-	/*
-	 * Just check to see if the device is online.  If it isn't, we
-	 * refuse to process any commands.  The device must be brought
-	 * online before trying any recovery commands
-	 */
-	if (unlikely(!scsi_device_online(sdev))) {
-		printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
-		       sdev->host->host_no, sdev->id, sdev->lun);
-		return BLKPREP_KILL;
-	}
-	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
-		/* OK, we're not in a running state don't prep
-		 * user commands */
-		if (sdev->sdev_state == SDEV_DEL) {
-			/* Device is fully deleted, no commands
-			 * at all allowed down */
-			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
-			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
-		}
-		/* OK, we only allow special commands (i.e. not
-		 * user initiated ones */
-		specials_only = sdev->sdev_state;
-	}
 
 	/*
 	 * The SPECIAL requests are things like character device or
@@ -1068,30 +1044,12 @@ static int scsi_prep_fn(struct request_q
 		} else
 			cmd = req->special;
 	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
-
-		if(unlikely(specials_only)) {
-			if(specials_only == SDEV_QUIESCE ||
-					specials_only == SDEV_BLOCK)
-				return BLKPREP_DEFER;
-			
-			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
-			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
-		}
-			
-			
-		/*
-		 * Now try and find a command block that we can use.
-		 */
 		if (!req->special) {
 			cmd = scsi_get_command(sdev, GFP_ATOMIC);
 			if (unlikely(!cmd))
 				goto defer;
 		} else
 			cmd = req->special;
-		
-		/* pull a tag out of the request if we have one */
-		cmd->tag = req->tag;
 	} else {
 		blk_dump_rq_flags(req, "SCSI bad req");
 		return BLKPREP_KILL;
@@ -1232,6 +1190,54 @@ static inline int scsi_host_queue_ready(
 }
 
 /*
+ * scsi_wait_reset: We will wait MIN_RESET_DELAY clock ticks after the
+ * last reset so we can avoid the drive not being ready.
+ *
+ * Called with no lock held and irq disabled.
+ */
+static inline void scsi_wait_reset(struct Scsi_Host *shost)
+{
+	unsigned long timeout = shost->last_reset + MIN_RESET_DELAY;
+
+	if (shost->resetting && time_before(jiffies, timeout)) {
+		int ticks_remaining = timeout - jiffies;
+		/*
+		 * NOTE: This may be executed from within an interrupt
+		 * handler!  This is bad, but for now, it'll do.  The
+		 * irq level of the interrupt handler has been masked
+		 * out by the platform dependent interrupt handling
+		 * code already, so the local_irq_enable() here will
+		 * not cause another call to the SCSI host's interrupt
+		 * handler (assuming there is one irq-level per host).
+		 */
+		local_irq_enable();
+
+		while (--ticks_remaining >= 0)
+			mdelay(1 + 999 / HZ);
+		shost->resetting = 0;
+
+		local_irq_disable();
+	}
+}
+
+/* 
+ * scsi_cmd_get_serial: Assign a serial number and pid to the request
+ * for error recovery and debugging purposes.
+ *
+ * Called with host_lock held.
+ */
+static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+{
+	cmd->serial_number = host->cmd_serial_number++;
+	if (cmd->serial_number == 0) 
+		cmd->serial_number = host->cmd_serial_number++;
+
+	cmd->pid = host->cmd_pid++;
+	if (cmd->pid == 0)
+		cmd->pid = host->cmd_pid++;
+}
+
+/*
  * Function:    scsi_request_fn()
  *
  * Purpose:     Main strategy routine for SCSI.
@@ -1246,108 +1252,131 @@ static void scsi_request_fn(struct reque
 {
 	struct scsi_device *sdev = q->queuedata;
 	struct Scsi_Host *shost = sdev->host;
-	struct scsi_cmnd *cmd;
 	struct request *req;
+	struct scsi_cmnd *cmd;
+	int ret = 0;
 
-	if(!get_device(&sdev->sdev_gendev))
-		/* We must be tearing the block queue down already */
-		return;
+	/* FIXME: Once fire & forgetters are fixed, this and the
+	 * unlock_irq/put_device/lock_irq dance at the end of this
+	 * function can go away. */
+	get_device(&sdev->sdev_gendev);
+
+	while ((req = elv_next_request(q))) {
+		enum scsi_device_state state;
+		int kill = 0, is_special = req->flags & REQ_SPECIAL;
 
-	/*
-	 * To start with, we keep looping until the queue is empty, or until
-	 * the host is no longer able to accept any more requests.
-	 */
-	while (!blk_queue_plugged(q)) {
-		int rtn;
-		/*
-		 * get next queueable request.  We do this early to make sure
-		 * that the request is fully prepared even if we cannot 
-		 * accept it.
-		 */
-		req = elv_next_request(q);
-		if (!req || !scsi_dev_queue_ready(q, sdev))
-			break;
+		cmd = req->special;
+		state = cmd->device->sdev_state;
 
-		if (unlikely(!scsi_device_online(sdev))) {
-			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
-			       sdev->host->host_no, sdev->id, sdev->lun);
-			blkdev_dequeue_request(req);
-			req->flags |= REQ_QUIET;
-			while (end_that_request_first(req, 0, req->nr_sectors))
-				;
-			end_that_request_last(req);
-			continue;
+		if (scsi_device_online(sdev) && state != SDEV_DEL &&
+		    (is_special || state != SDEV_CANCEL)) {
+			if (state == SDEV_BLOCK ||
+			    (!is_special && state == SDEV_QUIESCE))
+				break;
+			if (!scsi_dev_queue_ready(q, sdev))
+				break;
+		} else {
+			printk(KERN_ERR
+			       "scsi%d (%d:%d): rejecting I/O to %s\n",
+			       shost->host_no, sdev->id, sdev->lun,
+			       !scsi_device_online(sdev) ? "offline device" :
+			       (state == SDEV_DEL ? "dead device"
+						  : "device being removed"));
+			kill = 1;
 		}
 
-
-		/*
-		 * Remove the request from the request list.
-		 */
-		if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req)))
+		/* Start tag / remove from the request queue. */
+		if (blk_queue_tagged(q)) {
+			if (blk_queue_start_tag(q, req))
+				BUG();
+			cmd->tag = req->tag;
+		} else
 			blkdev_dequeue_request(req);
+
 		sdev->device_busy++;
 
+		/* Switch to host_lock. */
 		spin_unlock(q->queue_lock);
+		scsi_wait_reset(shost);
 		spin_lock(shost->host_lock);
 
-		if (!scsi_host_queue_ready(q, shost, sdev))
-			goto not_ready;
-		if (sdev->single_lun) {
-			if (scsi_target(sdev)->starget_sdev_user &&
-			    scsi_target(sdev)->starget_sdev_user != sdev)
-				goto not_ready;
-			scsi_target(sdev)->starget_sdev_user = sdev;
-		}
-		shost->host_busy++;
-
-		/*
-		 * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will
-		 *		take the lock again.
-		 */
-		spin_unlock_irq(shost->host_lock);
+		if (!kill && !test_bit(SHOST_CANCEL, &shost->shost_state)) {
+			if (!scsi_host_queue_ready(q, shost, sdev))
+				goto requeue_out;
+			if (sdev->single_lun) {
+				struct scsi_target *target = scsi_target(sdev);
+				if (target->starget_sdev_user &&
+				    target->starget_sdev_user != sdev)
+					goto requeue_out;
+				target->starget_sdev_user = sdev;
+			}
 
-		cmd = req->special;
-		if (unlikely(cmd == NULL)) {
-			printk(KERN_CRIT "impossible request in %s.\n"
-					 "please mail a stack trace to "
-					 "linux-scsi@vger.kernel.org",
-					 __FUNCTION__);
-			BUG();
+			shost->host_busy++;
+			scsi_log_send(cmd);
+			scsi_cmd_get_serial(shost, cmd);
+			scsi_add_timer(cmd, cmd->timeout_per_command,
+				       scsi_times_out);
+
+			cmd->state = SCSI_STATE_QUEUED;
+			cmd->owner = SCSI_OWNER_LOWLEVEL;
+
+			ret = shost->hostt->queuecommand(cmd, scsi_done);
+			if (ret == 0)
+				atomic_inc(&sdev->iorequest_cnt);
+			else {
+				SCSI_LOG_MLQUEUE(3,
+				    printk("%s: queuecommand deferred request (%d)\n",
+					   __FUNCTION__, ret));
+				/* Timer should be deleted while holding
+				 * the host_lock.  Once it gets released, we
+				 * don't know if cmd is still there or not. */
+				if (scsi_delete_timer(cmd)) {
+					shost->host_busy--;
+					goto block_requeue_out;
+				}
+			}
+		} else {
+			SCSI_LOG_MLQUEUE(3,
+			    printk("%s: rejecting request\n", __FUNCTION__));
+			shost->host_busy++;
+			atomic_inc(&sdev->iorequest_cnt);
+			cmd->result = DID_NO_CONNECT << 16;
+			__scsi_done(cmd);
 		}
 
-		/*
-		 * Dispatch the command to the low-level driver.
-		 */
-		rtn = scsi_dispatch_cmd(cmd);
-		spin_lock_irq(q->queue_lock);
-		if(rtn) {
-			/* we're refusing the command; because of
-			 * the way locks get dropped, we need to 
-			 * check here if plugging is required */
-			if(sdev->device_busy == 0)
-				blk_plug_device(q);
+		/* Switch back to queue_lock. */
+		spin_unlock(shost->host_lock);
+		spin_lock(q->queue_lock);
 
+		/* queuecommand failed and timer took the request, bail out. */
+		if (ret)
 			break;
-		}
-	}
 
+		/* The queue could have been plugged underneath us. */
+		if (blk_queue_plugged(q))
+			break;
+	}
 	goto out;
 
- not_ready:
-	spin_unlock_irq(shost->host_lock);
+ block_requeue_out:
+	if (ret == SCSI_MLQUEUE_DEVICE_BUSY)
+		sdev->device_blocked = sdev->max_device_blocked;
+	else
+		shost->host_blocked = shost->max_host_blocked;
+ requeue_out:
+	/* Switch back to queue_lock */
+	spin_unlock(shost->host_lock);
+	spin_lock(q->queue_lock);
 
-	/*
-	 * lock q, handle tag, requeue req, and decrement device_busy. We
-	 * must return with queue_lock held.
-	 *
-	 * Decrementing device_busy without checking it is OK, as all such
-	 * cases (host limits or settings) should run the queue at some
-	 * later time.
-	 */
-	spin_lock_irq(q->queue_lock);
+	cmd->state = SCSI_STATE_MLQUEUE;
+	cmd->owner = SCSI_OWNER_MIDLEVEL;
+
+	SCSI_LOG_MLQUEUE(3,
+	    printk("%s: requeueing request\n", __FUNCTION__));
+
+	req->flags |= REQ_SOFTBARRIER;	/* Don't pass this request. */
 	blk_requeue_request(q, req);
-	sdev->device_busy--;
-	if(sdev->device_busy == 0)
+	if (--sdev->device_busy == 0)
 		blk_plug_device(q);
  out:
 	/* must be careful here...if we trigger the ->remove() function


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (9 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn() Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31 10:32   ` Christoph Hellwig
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 12/13] scsi: replace scsi_queue_insert() with scsi_requeue_command() Tejun Heo
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 13/13] scsi: consolidate scsi_cmd_retry() calls in scsi_error.c Tejun Heo
  12 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

11_scsi_make_requeue_command_public.patch

	Add reprep argument to scsi_requeue_command(), remove
	redundant q argument, add code to set cmd->state/owner, and
	make the function public.  This patch is preparation for
	consolidating requeue paths.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_lib.c  |   23 ++++++++++++++---------
 scsi_priv.h |    1 +
 2 files changed, 15 insertions(+), 9 deletions(-)

Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
@@ -466,8 +466,8 @@ void scsi_device_unbusy(struct scsi_devi
  *
  * Purpose:	Handle post-processing of completed commands.
  *
- * Arguments:	q	- queue to operate on
- *		cmd	- command that may need to be requeued.
+ * Arguments:	cmd	- command that may need to be requeued.
+ *		reprep	- needs to prep the command again?
  *
  * Returns:	Nothing
  *
@@ -478,11 +478,16 @@ void scsi_device_unbusy(struct scsi_devi
  *		we need to request the blocks that come after the bad
  *		sector.
  */
-static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
+void scsi_requeue_command(struct scsi_cmnd *cmd, int reprep)
 {
+	struct request_queue *q = cmd->device->request_queue;
 	unsigned long flags;
 
-	cmd->request->flags &= ~REQ_DONTPREP;
+	cmd->state = SCSI_STATE_MLQUEUE;
+	cmd->owner = SCSI_OWNER_MIDLEVEL;
+
+	if (reprep)
+		cmd->request->flags &= ~REQ_DONTPREP;
 	cmd->request->flags |= REQ_SOFTBARRIER;
 
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -556,7 +561,7 @@ static struct scsi_cmnd *scsi_end_reques
 				 * leftovers in the front of the
 				 * queue, and goose the queue again.
 				 */
-				scsi_requeue_command(q, cmd);
+				scsi_requeue_command(cmd, 1);
 
 			return cmd;
 		}
@@ -818,7 +823,7 @@ void scsi_io_completion(struct scsi_cmnd
 				* media change, so we just retry the
 				* request and see what happens.  
 				*/
-				scsi_requeue_command(q, cmd);
+				scsi_requeue_command(cmd, 1);
 				return;
 			}
 			break;
@@ -839,7 +844,7 @@ void scsi_io_completion(struct scsi_cmnd
 				 * This will cause a retry with a 6-byte
 				 * command.
 				 */
-				scsi_requeue_command(q, cmd);
+				scsi_requeue_command(cmd, 1);
 				result = 0;
 			} else {
 				cmd = scsi_end_request(cmd, 0, this_count, 1);
@@ -852,7 +857,7 @@ void scsi_io_completion(struct scsi_cmnd
 			 * retry.
 			 */
 			if (sshdr.asc == 0x04 && sshdr.ascq == 0x01) {
-				scsi_requeue_command(q, cmd);
+				scsi_requeue_command(cmd, 1);
 				return;
 			}
 			printk(KERN_INFO "Device %s not ready.\n",
@@ -878,7 +883,7 @@ void scsi_io_completion(struct scsi_cmnd
 		 * recovery reasons.  Just retry the request
 		 * and see what happens.  
 		 */
-		scsi_requeue_command(q, cmd);
+		scsi_requeue_command(cmd, 1);
 		return;
 	}
 	if (result) {
Index: scsi-export/drivers/scsi/scsi_priv.h
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_priv.h	2005-03-31 18:06:20.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_priv.h	2005-03-31 18:06:22.000000000 +0900
@@ -96,6 +96,7 @@ extern int scsi_maybe_unblock_host(struc
 extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd);
 extern void scsi_device_unbusy(struct scsi_device *sdev);
 extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
+extern void scsi_requeue_command(struct scsi_cmnd *cmd, int reprep);
 extern void scsi_next_command(struct scsi_cmnd *cmd);
 extern void scsi_run_host_queues(struct Scsi_Host *shost);
 extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 12/13] scsi: replace scsi_queue_insert() with scsi_requeue_command()
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (10 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 13/13] scsi: consolidate scsi_cmd_retry() calls in scsi_error.c Tejun Heo
  12 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

12_scsi_consolidate_requeue_paths.patch

	Add scsi_device_unbusy() call to scsi_retry_command(), replace
	scsi_queue_insert() with scsi_requeue_command(), make
	scsi_softirq() use scsi_retry_command() for ADD_TO_MLQUEUE
	case too (with explicit device blocking), and make
	scsi_eh_flush_done_q() use scsi_retry_command().  While at it,
	remove leading and tailing empty comment lines from trivial
	comments.

	As scsi_queue_insert() has no users now, kill it.

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi.c       |   25 ++++++++++---------
 scsi_error.c |    2 -
 scsi_lib.c   |   74 -----------------------------------------------------------
 scsi_priv.h  |    3 --
 4 files changed, 15 insertions(+), 89 deletions(-)

Index: scsi-export/drivers/scsi/scsi.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi.c	2005-03-31 18:06:22.000000000 +0900
@@ -638,6 +638,7 @@ static void scsi_softirq(struct softirq_
 	while (!list_empty(&local_q)) {
 		struct scsi_cmnd *cmd = list_entry(local_q.next,
 						   struct scsi_cmnd, eh_entry);
+		struct scsi_device *sdev = cmd->device;
 		list_del_init(&cmd->eh_entry);
 
 		disposition = scsi_decide_disposition(cmd);
@@ -646,12 +647,12 @@ static void scsi_softirq(struct softirq_
 		case SUCCESS:
 			scsi_finish_command(cmd);
 			break;
+		case ADD_TO_MLQUEUE:
+			sdev->device_blocked = sdev->max_device_blocked;
+			/* fall thru */
 		case NEEDS_RETRY:
 			scsi_retry_command(cmd);
 			break;
-		case ADD_TO_MLQUEUE:
-			scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
-			break;
 		default:
 			if (!scsi_eh_scmd_add(cmd, 0))
 				scsi_finish_command(cmd);
@@ -669,20 +670,20 @@ static void scsi_softirq(struct softirq_
  *              level drivers should not become re-entrant as a result of
  *              this.
  */
-int scsi_retry_command(struct scsi_cmnd *cmd)
+void scsi_retry_command(struct scsi_cmnd *cmd)
 {
-	/*
-	 * Restore the SCSI command state.
-	 */
+	SCSI_LOG_MLQUEUE(1, printk("Retrying command %p\n", cmd));
+
+	scsi_device_unbusy(cmd->device);
+
+	/* Restore the SCSI command state. */
 	scsi_setup_cmd_retry(cmd);
 
-        /*
-         * Zero the sense information from the last time we tried
-         * this command.
-         */
+        /* Zero the sense information from the last time we tried
+         * this command. */
 	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
 
-	return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
+	scsi_requeue_command(cmd, 0);
 }
 
 /*
Index: scsi-export/drivers/scsi/scsi_error.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_error.c	2005-03-31 18:06:21.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_error.c	2005-03-31 18:06:22.000000000 +0900
@@ -1551,7 +1551,7 @@ static void scsi_eh_flush_done_q(struct 
 							  " retry cmd: %p\n",
 							  current->comm,
 							  scmd));
-				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
+				scsi_retry_command(scmd);
 		} else {
 			if (!scmd->result)
 				scmd->result |= (DRIVER_TIMEOUT << 24);
Index: scsi-export/drivers/scsi/scsi_lib.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_lib.c	2005-03-31 18:06:22.000000000 +0900
@@ -210,80 +210,6 @@ int scsi_insert_special_req(struct scsi_
 }
 
 /*
- * Function:    scsi_queue_insert()
- *
- * Purpose:     Insert a command in the midlevel queue.
- *
- * Arguments:   cmd    - command that we are adding to queue.
- *              reason - why we are inserting command to queue.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns:     Nothing.
- *
- * Notes:       We do this for one of two cases.  Either the host is busy
- *              and it cannot accept any more commands for the time being,
- *              or the device returned QUEUE_FULL and can accept no more
- *              commands.
- * Notes:       This could be called either from an interrupt context or a
- *              normal process context.
- */
-int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
-{
-	struct Scsi_Host *host = cmd->device->host;
-	struct scsi_device *device = cmd->device;
-	struct request_queue *q = device->request_queue;
-	unsigned long flags;
-
-	SCSI_LOG_MLQUEUE(1,
-		 printk("Inserting command %p into mlqueue\n", cmd));
-
-	/*
-	 * Next, set the appropriate busy bit for the device/host.
-	 *
-	 * If the host/device isn't busy, assume that something actually
-	 * completed, and that we should be able to queue a command now.
-	 *
-	 * Note that the prior mid-layer assumption that any host could
-	 * always queue at least one command is now broken.  The mid-layer
-	 * will implement a user specifiable stall (see
-	 * scsi_host.max_host_blocked and scsi_device.max_device_blocked)
-	 * if a command is requeued with no other commands outstanding
-	 * either for the device or for the host.
-	 */
-	if (reason == SCSI_MLQUEUE_HOST_BUSY)
-		host->host_blocked = host->max_host_blocked;
-	else if (reason == SCSI_MLQUEUE_DEVICE_BUSY)
-		device->device_blocked = device->max_device_blocked;
-
-	/*
-	 * Register the fact that we own the thing for now.
-	 */
-	cmd->state = SCSI_STATE_MLQUEUE;
-	cmd->owner = SCSI_OWNER_MIDLEVEL;
-
-	/*
-	 * Decrement the counters, since these commands are no longer
-	 * active on the host/device.
-	 */
-	scsi_device_unbusy(device);
-
-	/*
-	 * Requeue the command.  Turn on REQ_SOFTBARRIER to prevent
-	 * other requests from passing this request.
-	 */
-	cmd->request->flags |= REQ_SOFTBARRIER;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_requeue_request(q, cmd->request);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	scsi_run_queue(q);
-
-	return 0;
-}
-
-/*
  * Function:    scsi_do_req
  *
  * Purpose:     Queue a SCSI request
Index: scsi-export/drivers/scsi/scsi_priv.h
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_priv.h	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_priv.h	2005-03-31 18:06:22.000000000 +0900
@@ -62,7 +62,7 @@ extern int scsi_dispatch_cmd(struct scsi
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
 extern void scsi_done(struct scsi_cmnd *cmd);
-extern int scsi_retry_command(struct scsi_cmnd *cmd);
+extern void scsi_retry_command(struct scsi_cmnd *cmd);
 extern int scsi_insert_special_req(struct scsi_request *sreq, int);
 extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
 		struct scsi_request *sreq);
@@ -95,7 +95,6 @@ extern int scsi_eh_scmd_add(struct scsi_
 extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
 extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd);
 extern void scsi_device_unbusy(struct scsi_device *sdev);
-extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
 extern void scsi_requeue_command(struct scsi_cmnd *cmd, int reprep);
 extern void scsi_next_command(struct scsi_cmnd *cmd);
 extern void scsi_run_host_queues(struct Scsi_Host *shost);


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 13/13] scsi: consolidate scsi_cmd_retry() calls in scsi_error.c
  2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
                   ` (11 preceding siblings ...)
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 12/13] scsi: replace scsi_queue_insert() with scsi_requeue_command() Tejun Heo
@ 2005-03-31  9:08 ` Tejun Heo
  12 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-03-31  9:08 UTC (permalink / raw)
  To: James.Bottomley, axboe; +Cc: linux-scsi, linux-kernel

13_scsi_consolidate_cmd_retry_calls_in_eh.patch

	Replace all scsi_setup_cmd_retry() calls in scsi_error.c with
	a call just above scsi_finish_command() in scsi_eh_flush_done_q().

Signed-off-by: Tejun Heo <htejun@gmail.com>

 scsi_error.c |   25 +------------------------
 1 files changed, 1 insertion(+), 24 deletions(-)

Index: scsi-export/drivers/scsi/scsi_error.c
===================================================================
--- scsi-export.orig/drivers/scsi/scsi_error.c	2005-03-31 18:06:22.000000000 +0900
+++ scsi-export/drivers/scsi/scsi_error.c	2005-03-31 18:06:23.000000000 +0900
@@ -615,11 +615,6 @@ static int scsi_request_sense(struct scs
 
 	kfree(scsi_result);
 
-	/*
-	 * when we eventually call scsi_finish, we really wish to complete
-	 * the original request, so let's restore the original data. (db)
-	 */
-	scsi_setup_cmd_retry(scmd);
 	scmd->result = saved_result;
 	return rtn;
 }
@@ -641,14 +636,7 @@ static void scsi_eh_finish_cmd(struct sc
 {
 	scmd->device->host->host_failed--;
 	scmd->state = SCSI_STATE_BHQUEUE;
-
 	scsi_eh_eflags_clr_all(scmd);
-
-	/*
-	 * set this back so that the upper level can correctly free up
-	 * things.
-	 */
-	scsi_setup_cmd_retry(scmd);
 	list_move_tail(&scmd->eh_entry, done_q);
 }
 
@@ -785,12 +773,6 @@ retry_tur:
 	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
 
 	/*
-	 * when we eventually call scsi_finish, we really wish to complete
-	 * the original request, so let's restore the original data. (db)
-	 */
-	scsi_setup_cmd_retry(scmd);
-
-	/*
 	 * hey, we are done.  let's look to see what happened.
 	 */
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
@@ -913,12 +895,6 @@ static int scsi_eh_try_stu(struct scsi_c
 	rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT);
 
 	/*
-	 * when we eventually call scsi_finish, we really wish to complete
-	 * the original request, so let's restore the original data. (db)
-	 */
-	scsi_setup_cmd_retry(scmd);
-
-	/*
 	 * hey, we are done.  let's look to see what happened.
 	 */
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
@@ -1558,6 +1534,7 @@ static void scsi_eh_flush_done_q(struct 
 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish"
 							" cmd: %p\n",
 							current->comm, scmd));
+			scsi_setup_cmd_retry(scmd);
 			scsi_finish_command(scmd);
 		}
 	}


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions Tejun Heo
@ 2005-03-31 10:11   ` Christoph Hellwig
  2005-04-01  5:15     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:11 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

On Thu, Mar 31, 2005 at 06:08:10PM +0900, Tejun Heo wrote:
>  	struct list_head    siblings;   /* list of all devices on this host */
>  	struct list_head    same_target_siblings; /* just the devices sharing same target id */
>  
> -	volatile unsigned short device_busy;	/* commands actually active on low-level */
> +	unsigned short device_busy;	/* commands actually active on
> +					 * low-level. protected by sdev_lock. */

You should probably switch it to just unsigned.  The other 16bit are wasted
due to alignment anyway, and some architectures produce better code for 32bit
accesses.

> -	volatile unsigned short host_busy;   /* commands actually active on low-level */
> -	volatile unsigned short host_failed; /* commands that failed. */
> +
> +	/*
> +	 * The following two fields are protected with host_lock;
> +	 * however, eh routines can safely access during eh processing
> +	 * without acquiring the lock.
> +	 */
> +	unsigned short host_busy;	   /* commands actually active on low-level */
> +	unsigned short host_failed;	   /* commands that failed. */

Here it would actually increase the struct size but might make sense anyway.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
@ 2005-03-31 10:12   ` Christoph Hellwig
  2005-04-01  4:18     ` Tejun Heo
  2005-03-31 17:53   ` James Bottomley
  1 sibling, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:12 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

On Thu, Mar 31, 2005 at 06:07:55PM +0900, Tejun Heo wrote:
> 01_scsi_no_REQ_SPECIAL_on_requeue.patch
> 
> 	blk_insert_request() has 'reinsert' argument, which, when set,
> 	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
> 	request.  SCSI midlayer was the only user of this feature and
> 	all requeued requests become special requests defeating
> 	quiesce state.  This patch makes scsi midlayer use
> 	blk_requeue_request() for requeueing and removes 'reinsert'
> 	feature from blk_insert_request().
> 
> 	Note: In drivers/scsi/scsi_lib.c, scsi_single_lun_run() and
> 	scsi_run_queue() are moved upward unchanged.

That lest part doesn't belong into this patch at all.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer Tejun Heo
@ 2005-03-31 10:13   ` Christoph Hellwig
  2005-04-01  5:15     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:13 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

>  		/* Queue the command and wait for it to complete */
>  		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
>  		init_timer(&cmd->eh_timeout);
> +		cmd->eh_timeout.function = NULL;

I'd rather not see aic7xxx poke even deeper into this internal code.
Can you please switch it to use a timer of it's own first?


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn() Tejun Heo
@ 2005-03-31 10:20   ` Christoph Hellwig
  2005-04-01  5:20     ` Tejun Heo
  2005-03-31 18:07   ` James Bottomley
  1 sibling, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:20 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

> +/*
> + * Macro to determine the size of SCSI command. This macro takes vendor
> + * unique commands into account. SCSI commands in groups 6 and 7 are
> + * vendor unique and we will depend upon the command length being
> + * supplied correctly in cmd_len.
> + */
> +#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
> +				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)

should probably go to scsi.h as it's generally usefull.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up Tejun Heo
@ 2005-03-31 10:22   ` Christoph Hellwig
  2005-03-31 18:02   ` James Bottomley
  1 sibling, 0 replies; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:22 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

> -		/* 
> -		 * This sets up the scatter-gather table (allocating if
> -		 * required).
> -		 */
> +		/* This sets up the scatter-gather table (allocating if
> +		 * required). */

the old comment style is the preferred in linux, please leave it as-is
(here and in other places)


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public Tejun Heo
@ 2005-03-31 10:32   ` Christoph Hellwig
  2005-04-01  5:35     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 10:32 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel

> - * Arguments:	q	- queue to operate on
> - *		cmd	- command that may need to be requeued.
> + * Arguments:	cmd	- command that may need to be requeued.
> + *		reprep	- needs to prep the command again?
>   *
>   * Returns:	Nothing
>   *
> @@ -478,11 +478,16 @@ void scsi_device_unbusy(struct scsi_devi
>   *		we need to request the blocks that come after the bad
>   *		sector.
>   */
> -static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
> +void scsi_requeue_command(struct scsi_cmnd *cmd, int reprep)
>  {
> +	struct request_queue *q = cmd->device->request_queue;
>  	unsigned long flags;
>  
> -	cmd->request->flags &= ~REQ_DONTPREP;
> +	cmd->state = SCSI_STATE_MLQUEUE;
> +	cmd->owner = SCSI_OWNER_MIDLEVEL;
> +
> +	if (reprep)
> +		cmd->request->flags &= ~REQ_DONTPREP;

the flag is not needed, you can move the clearing of the flag to the
caller.  And given that there's lots of callers rename the
scsi_requeue_command without it to __scsi_requeue_command and make
scsi_requeue_command a tiny inline wrapper around it that clears it.


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn()
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn() Tejun Heo
@ 2005-03-31 11:14   ` Christoph Hellwig
  2005-04-01  5:44     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: Christoph Hellwig @ 2005-03-31 11:14 UTC (permalink / raw)
  To: Tejun Heo; +Cc: James.Bottomley, axboe, linux-scsi, linux-kernel


the changes look good to me (although I haven't tested any of your patches
yet), but the code flow is rather confusing.  What do you think about
the not even compile version of scsi_request_fn() below that should be
functionally identical to yours:


static void scsi_request_fn(struct request_queue *q)
{
	struct scsi_device *sdev = q->queuedata;
	struct Scsi_Host *shost = sdev->host;
	struct scsi_cmnd *cmd;
	struct request *req;
	enum scsi_device_state state;
	int ret = 0;

	/*
	 * FIXME: Once fire & forgetters are fixed, this and the
	 * unlock_irq/put_device/lock_irq dance at the end of this
	 * function can go away.
	 */
	get_device(&sdev->sdev_gendev);

	while ((req = elv_next_request(q))) {
		int is_special = (req->flags & REQ_SPECIAL), kill = 0;

		cmd = req->special;
		state = cmd->device->sdev_state;

		if (state == SDEV_BLOCK ||
		    (state == SDEV_QUIESCE && !is_special))
			goto out;
		else if (state == SDEV_OFFLINE || state == SDEV_DEL ||
			 (state == SDEV_CANCLE && !is_special)) {
			printk(KERN_ERR "scsi%d (%d:%d): "
					"rejecting I/O to %s\n",
					(state == SDEV_OFFLINE) ?
						"offline device" :
					 ((state == SDEV_DEL) ?
					  	"dead device" :
						"device being removed"));
			kill = 1;
		} else if (!scsi_dev_queue_ready(q, sdev))
			goto out;

		/* Start tag / remove from the request queue. */
		if (blk_queue_tagged(q)) {
			if (unlikely(blk_queue_start_tag(q, req)))
				BUG();
			cmd->tag = req->tag;
		} else
			blkdev_dequeue_request(req);

		sdev->device_busy++;

		/* Switch to host_lock. */
		spin_unlock(q->queue_lock);
		scsi_wait_reset(shost);
		spin_lock(shost->host_lock);

		if (kill || test_bit(SHOST_CANCEL, &shost->shost_state)) {
			SCSI_LOG_MLQUEUE(3,
				printk("%s: rejecting request\n", __FUNCTION__));
			shost->host_busy++;
			atomic_inc(&sdev->iorequest_cnt);
			cmd->result = DID_NO_CONNECT << 16;
			__scsi_done(cmd);
			goto relock;
		}
	
		if (!scsi_host_queue_ready(q, shost, sdev))
			goto requeue_out;

		if (sdev->single_lun) {
			struct scsi_target *target = scsi_target(sdev);
			if (target->starget_sdev_user &&
			    target->starget_sdev_user != sdev)
				goto requeue_out;
			target->starget_sdev_user = sdev;
		}

		shost->host_busy++;

		scsi_log_send(cmd);
		scsi_cmd_get_serial(shost, cmd);
		scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);

		cmd->state = SCSI_STATE_QUEUED;
		cmd->owner = SCSI_OWNER_LOWLEVEL;

		ret = shost->hostt->queuecommand(cmd, scsi_done);
		if (ret) {
			SCSI_LOG_MLQUEUE(3,
			    printk("%s: queuecommand deferred request (%d)\n",
				    __FUNCTION__, ret));

			/*
			 * Timer should be deleted while holding
			 * the host_lock.  Once it gets released, we
			 * don't know if cmd is still there or not.
			 */
			if (scsi_delete_timer(cmd)) {
				shost->host_busy--;
				goto block_requeue_out;
			}

			spin_unlock_irq(shost->host_lock);
			goto out_locked;
		}

		atomic_inc(&sdev->iorequest_cnt);

 relock:
		/* Switch back to queue_lock. */
		spin_unlock(shost->host_lock);
		spin_lock(q->queue_lock);

		/* The queue could have been plugged underneath us. */
		if (blk_queue_plugged(q))
			goto out;
	}

	goto out;

 block_requeue_out:
	if (ret == SCSI_MLQUEUE_DEVICE_BUSY)
		sdev->device_blocked = sdev->max_device_blocked;
	else
		shost->host_blocked = shost->max_host_blocked;
 requeue_out:
	/* Switch back to queue_lock */
	spin_unlock(shost->host_lock);
	spin_lock(q->queue_lock);

	cmd->state = SCSI_STATE_MLQUEUE;
	cmd->owner = SCSI_OWNER_MIDLEVEL;

	SCSI_LOG_MLQUEUE(3,
		printk("%s: requeueing request\n", __FUNCTION__));

	req->flags |= REQ_SOFTBARRIER;  /* Don't pass this request. */
	blk_requeue_request(q, req);
	if (--sdev->device_busy == 0)
		blk_plug_device(q);
 out:
	/*
	 * Must be careful here.  If we trigger the ->remove() function
	 * we cannot be holding the q lock
	 */
	spin_unlock_irq(q->queue_lock);
 out_locked:
	put_device(&sdev->sdev_gendev);
	spin_lock_irq(q->queue_lock);
}

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
  2005-03-31 10:12   ` Christoph Hellwig
@ 2005-03-31 17:53   ` James Bottomley
  2005-04-01  5:01     ` Tejun Heo
  1 sibling, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-03-31 17:53 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Thu, 2005-03-31 at 18:07 +0900, Tejun Heo wrote:
> 01_scsi_no_REQ_SPECIAL_on_requeue.patch
> 
> 	blk_insert_request() has 'reinsert' argument, which, when set,
> 	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
> 	request.  SCSI midlayer was the only user of this feature and
> 	all requeued requests become special requests defeating
> 	quiesce state.  This patch makes scsi midlayer use
> 	blk_requeue_request() for requeueing and removes 'reinsert'
> 	feature from blk_insert_request().

Well, REQ_SPECIAL is the signal to the mid-layer that we've allocated
the resources necessary to process the command, so in practice it will
be turned on for every requeue request (because we set it when the
command is prepared), so this patch would have no effect on your stated
quiesce problem.  However, if you think about how requests work with
head insertion and one command following another, there's really not a
huge problem here either.

The other reason I don't like this is that we've been trying hard to
sweep excess block knowledge out of the mid-layer.  I don't think
REQ_SOFTBARRIER is anything we really have to know about.

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure.
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure Tejun Heo
@ 2005-03-31 17:53   ` James Bottomley
  2005-04-01  5:14     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-03-31 17:53 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> 	Don't turn on REQ_SPECIAL on sgtable allocation failure.  This
> 	was the last place where REQ_SPECIAL is turned on for normal
> 	requests.

If you do this, you'll leak a command every time the sgtable allocation
fails.

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up Tejun Heo
  2005-03-31 10:22   ` Christoph Hellwig
@ 2005-03-31 18:02   ` James Bottomley
  2005-04-01  5:29     ` Tejun Heo
  1 sibling, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-03-31 18:02 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> -	 * come up when there is a medium error.  We have to treat
> -	 * these two cases differently.  We differentiate by looking
> -	 * at request->cmd, as this tells us the real story.
> +	 * come up when there is a medium error.

This comment isn't wrong.  That's exactly what this piece of code:

		if (sreq->sr_magic == SCSI_REQ_MAGIC) {

is all about ... that's how it distinguishes between the two cases.

The comment is misleading --- what it actually should say is that req-
>special has different contents depending upon the two cases, so
rephrasing it to be more accurate would be helpful.

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn() Tejun Heo
  2005-03-31 10:20   ` Christoph Hellwig
@ 2005-03-31 18:07   ` James Bottomley
  2005-04-01  5:25     ` Tejun Heo
  1 sibling, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-03-31 18:07 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> 	Move request preparations scattered in scsi_request_fn() and
> 	scsi_dispatch_cmd() into scsi_prep_fn().
> 
> 	* CDB_SIZE check in scsi_dispatch_cmd()
> 	* SCSI-2 LUN preparation in scsi_dispatch_cmd()
> 	* scsi_init_cmd_errh() in scsi_request_fn()
> 
> 	No invalid request reaches scsi_request_fn() anymore.

This one, I like, there's just one small problem:

You can't move scsi_init_cmd_errh() out of the request function path:
It's where we set up the sense buffer handling, so it has to be done
every time the command is prepared for execution (the prep function is
only called once)---think what happens if we turn a command around for
retry based on a sense indication.

So redo the patch and I'll put it in.

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-03-31 10:12   ` Christoph Hellwig
@ 2005-04-01  4:18     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  4:18 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

On Thu, Mar 31, 2005 at 11:12:11AM +0100, Christoph Hellwig wrote:
> On Thu, Mar 31, 2005 at 06:07:55PM +0900, Tejun Heo wrote:
> > 01_scsi_no_REQ_SPECIAL_on_requeue.patch
> > 
> > 	blk_insert_request() has 'reinsert' argument, which, when set,
> > 	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
> > 	request.  SCSI midlayer was the only user of this feature and
> > 	all requeued requests become special requests defeating
> > 	quiesce state.  This patch makes scsi midlayer use
> > 	blk_requeue_request() for requeueing and removes 'reinsert'
> > 	feature from blk_insert_request().
> > 
> > 	Note: In drivers/scsi/scsi_lib.c, scsi_single_lun_run() and
> > 	scsi_run_queue() are moved upward unchanged.
> 
> That lest part doesn't belong into this patch at all.

 Actually, it is, as scsi_queue_insert() is changed to call
scsi_run_queue() explicitly.  However, scsi_queue_insert() is removed
later, so the change is pretty dumb.  Maybe I'll add prototype and
remove it together later, or reorder patches.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-03-31 17:53   ` James Bottomley
@ 2005-04-01  5:01     ` Tejun Heo
  2005-04-01 18:09       ` James Bottomley
  0 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:01 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Hello, James.

On Thu, Mar 31, 2005 at 11:53:20AM -0600, James Bottomley wrote:
> On Thu, 2005-03-31 at 18:07 +0900, Tejun Heo wrote:
> > 01_scsi_no_REQ_SPECIAL_on_requeue.patch
> > 
> > 	blk_insert_request() has 'reinsert' argument, which, when set,
> > 	turns on REQ_SPECIAL and REQ_SOFTBARRIER and requeues the
> > 	request.  SCSI midlayer was the only user of this feature and
> > 	all requeued requests become special requests defeating
> > 	quiesce state.  This patch makes scsi midlayer use
> > 	blk_requeue_request() for requeueing and removes 'reinsert'
> > 	feature from blk_insert_request().
> 
> Well, REQ_SPECIAL is the signal to the mid-layer that we've allocated
> the resources necessary to process the command, so in practice it will
> be turned on for every requeue request (because we set it when the
> command is prepared),

 Sorry, but where?  AFAICT, only blk_insert_request() and
scsi_init_io() on sgtable allocation failure set REQ_SPECIAL during
scsi midlayer processing.  This patch replaces blk_insert_request()
with blk_requeue_request() and the next patch removes REQ_SPECIAL
setting in scsi_init_io().

 REQ_SPECIAL is currently overloaded to mean two different things.

 * The request is a special request.
 * The request has been requeued using scsi_queue_insert().
   i.e. It has been prepped.

 However, #2 can be tested by rq->special != NULL condition, and, in
fact, the prep_fn already has the code.  This is why this and the next
patch don't break the requeue path.  IMHO, this proves the subtlety of
the REQ_SPECIAL semantics.  Which path is taken on which case gets
kind of confusing by meaning two different things with REQ_SPECIAL.

> so this patch would have no effect on your stated
> quiesce problem.  However, if you think about how requests work with
> head insertion and one command following another, there's really not a
> huge problem here either.

 I agree that it's not a huge problem, but it's subtle and has the
potential of causing probably non-destructive but confusing behavior
on rare cases.

> The other reason I don't like this is that we've been trying hard to
> sweep excess block knowledge out of the mid-layer.  I don't think
> REQ_SOFTBARRIER is anything we really have to know about.

 We currently requeue using two different block functions.

 * blk_insert_request(): this function does two things
	1. enqueue special requests
	2. turn on REQ_SPECIAL|REQ_SOFTBARRIER and call
	   blk_requeue_request().  This is used only by scsi midlayer.
 * blk_requeue_request()

 REQ_SOFTBARRIER tells the request queue that other requests shouldn't
pass this one.  We need this to be set for prepped requests;
otherwise, it may, theoretically, deadlock (unprepped request waiting
for the prepped request back in the queue).  So, the current code

 * depends on blk_insert_request() sets REQ_SOFTBARRIER when
   requeueing.  It works but nothing in the interface or semantics
   is clear about it.  Why expect a request reinserted using
   blk_insert_request() gets REQ_SOFTBARRIER turned on while a request
   reinserted with blk_requeue_request() doesn't?  or why are there
   two different paths doing mostly the same thing with slightly
   different semantics?
 * requeueing using blk_requeue_request() in scsi_request_fn() doesn't
   turn on either REQ_SPECIAL or REQ_SOFTBARRIER.  Missing REQ_SPECIAL
   is okay, as we have the extra path in prep_fn (if it ever gets requeued
   due to medium failure, so gets re-prepped), but missing
   REQ_SOFTBARRIER can *theoretically* cause problem.

 So, it's more likely becoming less dependent on unobvious behavior of
block layer.  As we need the request to stay on top, we tell the block
layer to do so, instead of depending on blk_insert_request()
unobviously doing it for us.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure.
  2005-03-31 17:53   ` James Bottomley
@ 2005-04-01  5:14     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:14 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Hello, James.

On Thu, Mar 31, 2005 at 11:53:45AM -0600, James Bottomley wrote:
> On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> > 	Don't turn on REQ_SPECIAL on sgtable allocation failure.  This
> > 	was the last place where REQ_SPECIAL is turned on for normal
> > 	requests.
> 
> If you do this, you'll leak a command every time the sgtable allocation
> fails.

 AFAICT, not really.  We don't allocate another scsi_cmnd for normal
requests if req->special != NULL.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions
  2005-03-31 10:11   ` Christoph Hellwig
@ 2005-04-01  5:15     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:15 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

 Hello, Chritoph.

On Thu, Mar 31, 2005 at 11:11:45AM +0100, Christoph Hellwig wrote:
> On Thu, Mar 31, 2005 at 06:08:10PM +0900, Tejun Heo wrote:
> >  	struct list_head    siblings;   /* list of all devices on this host */
> >  	struct list_head    same_target_siblings; /* just the devices sharing same target id */
> >  
> > -	volatile unsigned short device_busy;	/* commands actually active on low-level */
> > +	unsigned short device_busy;	/* commands actually active on
> > +					 * low-level. protected by sdev_lock. */
> 
> You should probably switch it to just unsigned.  The other 16bit are wasted
> due to alignment anyway, and some architectures produce better code for 32bit
> accesses.
> 
> > -	volatile unsigned short host_busy;   /* commands actually active on low-level */
> > -	volatile unsigned short host_failed; /* commands that failed. */
> > +
> > +	/*
> > +	 * The following two fields are protected with host_lock;
> > +	 * however, eh routines can safely access during eh processing
> > +	 * without acquiring the lock.
> > +	 */
> > +	unsigned short host_busy;	   /* commands actually active on low-level */
> > +	unsigned short host_failed;	   /* commands that failed. */
> 
> Here it would actually increase the struct size but might make sense anyway.

 Sure, I'll make them unsigned.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer
  2005-03-31 10:13   ` Christoph Hellwig
@ 2005-04-01  5:15     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:15 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

 Hello, Chritoph.

On Thu, Mar 31, 2005 at 11:13:53AM +0100, Christoph Hellwig wrote:
> >  		/* Queue the command and wait for it to complete */
> >  		/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
> >  		init_timer(&cmd->eh_timeout);
> > +		cmd->eh_timeout.function = NULL;
> 
> I'd rather not see aic7xxx poke even deeper into this internal code.
> Can you please switch it to use a timer of it's own first?

 Yes, I'll.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-03-31 10:20   ` Christoph Hellwig
@ 2005-04-01  5:20     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:20 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

 Hello, Christoph.

On Thu, Mar 31, 2005 at 11:20:40AM +0100, Christoph Hellwig wrote:
> > +/*
> > + * Macro to determine the size of SCSI command. This macro takes vendor
> > + * unique commands into account. SCSI commands in groups 6 and 7 are
> > + * vendor unique and we will depend upon the command length being
> > + * supplied correctly in cmd_len.
> > + */
> > +#define CDB_SIZE(cmd)	(((((cmd)->cmnd[0] >> 5) & 7) < 6) ? \
> > +				COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
> 
> should probably go to scsi.h as it's generally usefull.

 I don't know.  Currently it's used only in one place.  Actually, I
was thinking about moving it into the function where it's used.  But
if it's useful, renaming it to something like SCSI_CMD_CDB_SIZE()
(maybe make it inline function?) and moving to scsi.h shouldn't be any
problem.  I think we need to hear other people's opinions.  Some
inputs please.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-03-31 18:07   ` James Bottomley
@ 2005-04-01  5:25     ` Tejun Heo
  2005-04-04 18:39       ` James Bottomley
  0 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:25 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Hello, James.

On Thu, Mar 31, 2005 at 12:07:44PM -0600, James Bottomley wrote:
> On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> > 	Move request preparations scattered in scsi_request_fn() and
> > 	scsi_dispatch_cmd() into scsi_prep_fn().
> > 
> > 	* CDB_SIZE check in scsi_dispatch_cmd()
> > 	* SCSI-2 LUN preparation in scsi_dispatch_cmd()
> > 	* scsi_init_cmd_errh() in scsi_request_fn()
> > 
> > 	No invalid request reaches scsi_request_fn() anymore.
> 
> This one, I like, there's just one small problem:
> 
> You can't move scsi_init_cmd_errh() out of the request function path:
> It's where we set up the sense buffer handling, so it has to be done
> every time the command is prepared for execution (the prep function is
> only called once)---think what happens if we turn a command around for
> retry based on a sense indication.
> 
> So redo the patch and I'll put it in.

 Ah.. with later requeue path consolidation patches, all requests get
their sense buffer cleared during requeueing, which, IMHO, is more
logical.  Moving scsi_init_cmd_errh() should come after the patch.
Sorry. :-)

 I'll make another take of this patchset (maybe subset) after issues
are resolved.  I'll split and reorder relocation of scsi_init_cmd_errh
then.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up
  2005-03-31 18:02   ` James Bottomley
@ 2005-04-01  5:29     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:29 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Hello, James.

On Thu, Mar 31, 2005 at 12:02:20PM -0600, James Bottomley wrote:
> On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> > -	 * come up when there is a medium error.  We have to treat
> > -	 * these two cases differently.  We differentiate by looking
> > -	 * at request->cmd, as this tells us the real story.
> > +	 * come up when there is a medium error.
> 
> This comment isn't wrong.  That's exactly what this piece of code:
> 
> 		if (sreq->sr_magic == SCSI_REQ_MAGIC) {
> 
> is all about ... that's how it distinguishes between the two cases.
> 
> The comment is misleading --- what it actually should say is that req-
> >special has different contents depending upon the two cases, so
> rephrasing it to be more accurate would be helpful.

 Yes, it was misleading, even more so with previous REQ_SPECIAL
patches.  I'll rewrite the comment once we resolve the REQ_SPECIAL
issue.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public
  2005-03-31 10:32   ` Christoph Hellwig
@ 2005-04-01  5:35     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:35 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

 Hello, Christoph.

On Thu, Mar 31, 2005 at 11:32:03AM +0100, Christoph Hellwig wrote:
> > - * Arguments:	q	- queue to operate on
> > - *		cmd	- command that may need to be requeued.
> > + * Arguments:	cmd	- command that may need to be requeued.
> > + *		reprep	- needs to prep the command again?
> >   *
> >   * Returns:	Nothing
> >   *
> > @@ -478,11 +478,16 @@ void scsi_device_unbusy(struct scsi_devi
> >   *		we need to request the blocks that come after the bad
> >   *		sector.
> >   */
> > -static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
> > +void scsi_requeue_command(struct scsi_cmnd *cmd, int reprep)
> >  {
> > +	struct request_queue *q = cmd->device->request_queue;
> >  	unsigned long flags;
> >  
> > -	cmd->request->flags &= ~REQ_DONTPREP;
> > +	cmd->state = SCSI_STATE_MLQUEUE;
> > +	cmd->owner = SCSI_OWNER_MIDLEVEL;
> > +
> > +	if (reprep)
> > +		cmd->request->flags &= ~REQ_DONTPREP;
> 
> the flag is not needed, you can move the clearing of the flag to the
> caller.  And given that there's lots of callers rename the
> scsi_requeue_command without it to __scsi_requeue_command and make
> scsi_requeue_command a tiny inline wrapper around it that clears it.

 I opt for scsi_requeue_command() and scsi_requeue_command_reprep()
for clarity (the latter being static inline).

 Thanks a lot for all your inputs. :-)

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn()
  2005-03-31 11:14   ` Christoph Hellwig
@ 2005-04-01  5:44     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01  5:44 UTC (permalink / raw)
  To: Christoph Hellwig, James.Bottomley, axboe, linux-scsi, linux-kernel

 Hello, Christoph.

On Thu, Mar 31, 2005 at 12:14:16PM +0100, Christoph Hellwig wrote:
> the changes look good to me (although I haven't tested any of your patches
> yet), but the code flow is rather confusing.  What do you think about
> the not even compile version of scsi_request_fn() below that should be
> functionally identical to yours:

 Yes, it's rather confusing.  I was a bit concerned about forward
gotos which are not error handling/exit and possible needs for
unlikely()'s by putting error handling on hotter path, IOW, untaken
forward branch.  For the records, I think the likely/unlikely thingies
are ugly & over-optimization in many cases.

 However, your code is aesthetically much better.  If there are no
opjections regarding the forward non-error-exit jumps, I'll reorganize
the code mostly as you suggested in the next take of this patchset.

 Thanks a lot. :-)

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-04-01  5:01     ` Tejun Heo
@ 2005-04-01 18:09       ` James Bottomley
  2005-04-01 22:21         ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-04-01 18:09 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Fri, 2005-04-01 at 14:01 +0900, Tejun Heo wrote:
> > Well, REQ_SPECIAL is the signal to the mid-layer that we've allocated
> > the resources necessary to process the command, so in practice it will
> > be turned on for every requeue request (because we set it when the
> > command is prepared),
> 
>  Sorry, but where?  AFAICT, only blk_insert_request() and
> scsi_init_io() on sgtable allocation failure set REQ_SPECIAL during
> scsi midlayer processing.  This patch replaces blk_insert_request()
> with blk_requeue_request() and the next patch removes REQ_SPECIAL
> setting in scsi_init_io().
> 
>  REQ_SPECIAL is currently overloaded to mean two different things.
> 
>  * The request is a special request.
>  * The request has been requeued using scsi_queue_insert().
>    i.e. It has been prepped.

But its true meaning is defined by the block layer (since it's a block
flag).  It's supposed to mean that the ->special field of the request is
in use to carry data meaningful to the underlying driver.  SCSI sets it
on that basis.

So, if I understand correctly, based on the fact that the current block
code in fact never bothers with REQ_SPECIAL, but only checks req-
>special, you're proposing that we need never actually set REQ_SPECIAL
when making use of the ->special field?  Thus you want to use
REQ_SPECIAL to distinguish between internally generated commands and
external commands?  That sounds fine as long as the block API gets
updated to reflect this (comments in linux/blkdev.h shoudl be fine).

> > The other reason I don't like this is that we've been trying hard to
> > sweep excess block knowledge out of the mid-layer.  I don't think
> > REQ_SOFTBARRIER is anything we really have to know about.
> 
>  We currently requeue using two different block functions.
> 
>  * blk_insert_request(): this function does two things
> 	1. enqueue special requests
> 	2. turn on REQ_SPECIAL|REQ_SOFTBARRIER and call
> 	   blk_requeue_request().  This is used only by scsi midlayer.
>  * blk_requeue_request()
> 
>  REQ_SOFTBARRIER tells the request queue that other requests shouldn't
> pass this one.  We need this to be set for prepped requests;
> otherwise, it may, theoretically, deadlock (unprepped request waiting
> for the prepped request back in the queue).  So, the current code
> 
>  * depends on blk_insert_request() sets REQ_SOFTBARRIER when
>    requeueing.  It works but nothing in the interface or semantics
>    is clear about it.  Why expect a request reinserted using
>    blk_insert_request() gets REQ_SOFTBARRIER turned on while a request
>    reinserted with blk_requeue_request() doesn't?  or why are there
>    two different paths doing mostly the same thing with slightly
>    different semantics?
>  * requeueing using blk_requeue_request() in scsi_request_fn() doesn't
>    turn on either REQ_SPECIAL or REQ_SOFTBARRIER.  Missing REQ_SPECIAL
>    is okay, as we have the extra path in prep_fn (if it ever gets requeued
>    due to medium failure, so gets re-prepped), but missing
>    REQ_SOFTBARRIER can *theoretically* cause problem.
> 
>  So, it's more likely becoming less dependent on unobvious behavior of
> block layer.  As we need the request to stay on top, we tell the block
> layer to do so, instead of depending on blk_insert_request()
> unobviously doing it for us.

But that's the point.  This is non obvious behaviour in the block layer,
so SCSI doesn't want to know about it (and the block maintainer won't
want to trawl through the SCSI and other block drivers altering it if it
changes).  If the bug is that the block layer isn't setting it on all
our requeues where it should, then either we're using the wrong API or
the block layer API is buggy.

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn()
  2005-03-31  9:08 ` [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn() Tejun Heo
@ 2005-04-01 18:23   ` James Bottomley
  2005-04-01 23:07     ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-04-01 18:23 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> 	When scsi_init_io() returns BLKPREP_DEFER or BLKPREP_KILL,
> 	it's supposed to free resources itself.  This patch
> 	consolidates defer and kill handling into scsi_prep_fn().
> 	This fixes a queue stall bug which occurred when sgtable
> 	allocation failed and device_busy == 0.

This one I like, but I think it doesn't go far enough.  There are
situations where a re-queue can also re-prepare, which means we leak sg
lists and commands on BLKPREP_KILL because of SCSI state.

How about the attached.

Note, I've also altered the prepare function so req->special never gets
altered if it points to a scsi_request. Previously it would be altered
to point to the command, but now we couldn't put the command since the
scsi_request we can't get to also has a copy of if.  So, if you can make
your later REQ_SPECIAL removal work, we can dispense with sr_magic and
simply use REQ_SPECIAL as the discriminator for the contents of req-
>special.

James

===== drivers/scsi/scsi_lib.c 1.153 vs edited =====
--- 1.153/drivers/scsi/scsi_lib.c	2005-03-30 13:49:45 -06:00
+++ edited/drivers/scsi/scsi_lib.c	2005-04-01 12:18:36 -06:00
@@ -63,6 +63,21 @@
 }; 	
 #undef SP
 
+static inline struct scsi_request *scsi_request(struct request *req) {
+	struct scsi_request *sreq = req->special;
+
+	if (sreq && sreq->sr_magic == SCSI_REQ_MAGIC)
+		return sreq;
+	return NULL;
+}
+
+static struct scsi_cmnd *scsi_command(struct request *req) {
+	struct scsi_request *sreq = scsi_request(req);
+
+	if (sreq)
+		return sreq->sr_command;
+	return req->special;
+}
 
 /*
  * Function:    scsi_insert_special_req()
@@ -626,6 +641,9 @@
 {
 	struct scsi_host_sg_pool *sgp;
 
+	if (sgl == NULL)
+		return;
+
 	BUG_ON(index > SG_MEMPOOL_NR);
 
 	sgp = scsi_sg_pools + index;
@@ -973,9 +991,6 @@
 	printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
 			req->current_nr_sectors);
 
-	/* release the command and kill it */
-	scsi_release_buffers(cmd);
-	scsi_put_command(cmd);
 	return BLKPREP_KILL;
 }
 
@@ -1041,7 +1056,7 @@
 	if (unlikely(!scsi_device_online(sdev))) {
 		printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
 		       sdev->host->host_no, sdev->id, sdev->lun);
-		return BLKPREP_KILL;
+		goto kill;
 	}
 	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
 		/* OK, we're not in a running state don't prep
@@ -1051,7 +1066,7 @@
 			 * at all allowed down */
 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
 			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
+			goto kill;
 		}
 		/* OK, we only allow special commands (i.e. not
 		 * user initiated ones */
@@ -1069,15 +1084,14 @@
 	 * at request->cmd, as this tells us the real story.
 	 */
 	if (req->flags & REQ_SPECIAL) {
-		struct scsi_request *sreq = req->special;
+		struct scsi_request *sreq = scsi_request(req);
 
-		if (sreq->sr_magic == SCSI_REQ_MAGIC) {
+		if (sreq) {
 			cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC);
 			if (unlikely(!cmd))
 				goto defer;
 			scsi_init_cmd_from_req(cmd, sreq);
-		} else
-			cmd = req->special;
+		}
 	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 
 		if(unlikely(specials_only)) {
@@ -1087,7 +1101,7 @@
 			
 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
 			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
+			goto kill;
 		}
 			
 			
@@ -1098,22 +1112,16 @@
 			cmd = scsi_get_command(sdev, GFP_ATOMIC);
 			if (unlikely(!cmd))
 				goto defer;
-		} else
-			cmd = req->special;
-		
+			req->special = cmd;
+			cmd->request = req;
+		}
 		/* pull a tag out of the request if we have one */
 		cmd->tag = req->tag;
 	} else {
 		blk_dump_rq_flags(req, "SCSI bad req");
-		return BLKPREP_KILL;
+		goto kill;
 	}
-	
-	/* note the overloading of req->special.  When the tag
-	 * is active it always means cmd.  If the tag goes
-	 * back for re-queueing, it may be reset */
-	req->special = cmd;
-	cmd->request = req;
-	
+
 	/*
 	 * FIXME: drop the lock here because the functions below
 	 * expect to be called without the queue lock held.  Also,
@@ -1143,18 +1151,26 @@
 		 * required).
 		 */
 		ret = scsi_init_io(cmd);
-		if (ret)	/* BLKPREP_KILL return also releases the command */
-			return ret;
+		switch (ret) {
+		case 0:
+			/* successful initialisation */
+			break;
+
+		case BLKPREP_DEFER:
+			goto defer;
+
+		default:
+			/* Unrecognised return, fall through */
+		case BLKPREP_KILL:
+			goto kill;
+		}
 		
 		/*
 		 * Initialize the actual SCSI command for this request.
 		 */
 		drv = *(struct scsi_driver **)req->rq_disk->private_data;
-		if (unlikely(!drv->init_command(cmd))) {
-			scsi_release_buffers(cmd);
-			scsi_put_command(cmd);
-			return BLKPREP_KILL;
-		}
+		if (unlikely(!drv->init_command(cmd)))
+			goto kill;
 	}
 
 	/*
@@ -1170,6 +1186,22 @@
 	if (sdev->device_busy == 0)
 		blk_plug_device(q);
 	return BLKPREP_DEFER;
+ kill:
+	/* Here we have to release every resource associated with the
+	 * request because this will complete at the request level
+	 * (req->end_io), not the scsi command level, so no scsi
+	 * routine will get to free the associated resources */
+
+	cmd = scsi_command(req);
+
+	if (cmd) {
+		struct scsi_request *sreq = scsi_request(req);
+		scsi_release_buffers(cmd);
+		scsi_put_command(cmd);
+		if (sreq)
+			sreq->sr_command = NULL;
+	}
+	return BLKPREP_KILL;
 }
 
 /*
@@ -1341,7 +1373,7 @@
 		 */
 		spin_unlock_irq(shost->host_lock);
 
-		cmd = req->special;
+		cmd = scsi_command(req);
 		if (unlikely(cmd == NULL)) {
 			printk(KERN_CRIT "impossible request in %s.\n"
 					 "please mail a stack trace to "



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing
  2005-04-01 18:09       ` James Bottomley
@ 2005-04-01 22:21         ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01 22:21 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Greetings, James.

On Fri, Apr 01, 2005 at 12:09:48PM -0600, James Bottomley wrote:
> On Fri, 2005-04-01 at 14:01 +0900, Tejun Heo wrote:
> > > Well, REQ_SPECIAL is the signal to the mid-layer that we've allocated
> > > the resources necessary to process the command, so in practice it will
> > > be turned on for every requeue request (because we set it when the
> > > command is prepared),
> > 
> >  Sorry, but where?  AFAICT, only blk_insert_request() and
> > scsi_init_io() on sgtable allocation failure set REQ_SPECIAL during
> > scsi midlayer processing.  This patch replaces blk_insert_request()
> > with blk_requeue_request() and the next patch removes REQ_SPECIAL
> > setting in scsi_init_io().
> > 
> >  REQ_SPECIAL is currently overloaded to mean two different things.
> > 
> >  * The request is a special request.
> >  * The request has been requeued using scsi_queue_insert().
> >    i.e. It has been prepped.
> 
> But its true meaning is defined by the block layer (since it's a block
> flag).  It's supposed to mean that the ->special field of the request is
> in use to carry data meaningful to the underlying driver.  SCSI sets it
> on that basis.
>
> So, if I understand correctly, based on the fact that the current block
> code in fact never bothers with REQ_SPECIAL, but only checks req-
> >special, you're proposing that we need never actually set REQ_SPECIAL
> when making use of the ->special field?  Thus you want to use
> REQ_SPECIAL to distinguish between internally generated commands and
> external commands?  That sounds fine as long as the block API gets
> updated to reflect this (comments in linux/blkdev.h shoudl be fine).

 Yeap, That's what I'm proposing.  Block API never cares about
REQ_SPECIAL flag or ->special field except for when determining if
requests can be merged - both fields are independently checked in this
case.  And IDE driver already uses the flag regardless of ->special
field.  Do you want me to clear up the comment?

> > > The other reason I don't like this is that we've been trying hard to
> > > sweep excess block knowledge out of the mid-layer.  I don't think
> > > REQ_SOFTBARRIER is anything we really have to know about.
> > 
> >  We currently requeue using two different block functions.
> > 
> >  * blk_insert_request(): this function does two things
> > 	1. enqueue special requests
> > 	2. turn on REQ_SPECIAL|REQ_SOFTBARRIER and call
> > 	   blk_requeue_request().  This is used only by scsi midlayer.
> >  * blk_requeue_request()
> > 
> >  REQ_SOFTBARRIER tells the request queue that other requests shouldn't
> > pass this one.  We need this to be set for prepped requests;
> > otherwise, it may, theoretically, deadlock (unprepped request waiting
> > for the prepped request back in the queue).  So, the current code
> > 
> >  * depends on blk_insert_request() sets REQ_SOFTBARRIER when
> >    requeueing.  It works but nothing in the interface or semantics
> >    is clear about it.  Why expect a request reinserted using
> >    blk_insert_request() gets REQ_SOFTBARRIER turned on while a request
> >    reinserted with blk_requeue_request() doesn't?  or why are there
> >    two different paths doing mostly the same thing with slightly
> >    different semantics?
> >  * requeueing using blk_requeue_request() in scsi_request_fn() doesn't
> >    turn on either REQ_SPECIAL or REQ_SOFTBARRIER.  Missing REQ_SPECIAL
> >    is okay, as we have the extra path in prep_fn (if it ever gets requeued
> >    due to medium failure, so gets re-prepped), but missing
> >    REQ_SOFTBARRIER can *theoretically* cause problem.
> > 
> >  So, it's more likely becoming less dependent on unobvious behavior of
> > block layer.  As we need the request to stay on top, we tell the block
> > layer to do so, instead of depending on blk_insert_request()
> > unobviously doing it for us.
> 
> But that's the point.  This is non obvious behaviour in the block layer,
> so SCSI doesn't want to know about it (and the block maintainer won't
> want to trawl through the SCSI and other block drivers altering it if it
> changes).

 Yes, it's non-obvious behavior of blk_insert_request() when used for
requeueing and, SCSI is the *only* user.  This patch removes the
unobvious path.

> If the bug is that the block layer isn't setting it on all
> our requeues where it should, then either we're using the wrong API or
> the block layer API is buggy.

 But block drivers in general don't have to inhibit reordering
requeued requests.  SCSI midlayer caches resources over requeueing, so
it's SCSI midlayer's requirement that requeued requests shouldn't be
passed.  IOW, it's SCSI midlayer's responsibility to tell the block
layer not to reschedule the request.  REQ_SOFTBARRIER has well-defined
meaning to tell just that.  It's not a block-layer internal thing.
It's a public interface.

 IOW, this patch uses well-defined flag to tell the block layer what
the SCSI midlayer wants.  I don't see any problem there.  If you're
uncomfortable with using REQ_* flag directly, writing a wrapper
shouldn't be a problem, but, IMHO, current form seems fine.

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn()
  2005-04-01 18:23   ` James Bottomley
@ 2005-04-01 23:07     ` Tejun Heo
  0 siblings, 0 replies; 42+ messages in thread
From: Tejun Heo @ 2005-04-01 23:07 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

 Greetings, James. :-)

On Fri, Apr 01, 2005 at 12:23:37PM -0600, James Bottomley wrote:
> On Thu, 2005-03-31 at 18:08 +0900, Tejun Heo wrote:
> > 	When scsi_init_io() returns BLKPREP_DEFER or BLKPREP_KILL,
> > 	it's supposed to free resources itself.  This patch
> > 	consolidates defer and kill handling into scsi_prep_fn().
> > 	This fixes a queue stall bug which occurred when sgtable
> > 	allocation failed and device_busy == 0.
> 
> This one I like, but I think it doesn't go far enough.  There are
> situations where a re-queue can also re-prepare, which means we leak sg
> lists and commands on BLKPREP_KILL because of SCSI state.

 With later request_fn() rewrite patch, all state checking are moved
to request_fn() and gets terminated with __scsi_done().  prep_fn()
only kills invalid (so, unprepped) requests.  It's in the fixed bugs
list of the request_fn() rewrite patch.  BTW, there's one more path
which leaks cmnd/sgtable, the end_that_request_*() on offline path of
request_fn() which is also fixed by request_fn() rewrite patch.

 I'm sorry about not mentioning that the bug is fixed in the later
patch.  Please review request_fn() rewrite patch.

> How about the attached.
> 
> Note, I've also altered the prepare function so req->special never gets
> altered if it points to a scsi_request. Previously it would be altered
> to point to the command, but now we couldn't put the command since the
> scsi_request we can't get to also has a copy of if.  So, if you can make
> your later REQ_SPECIAL removal work, we can dispense with sr_magic and
> simply use REQ_SPECIAL as the discriminator for the contents of req-
> >special.
> 
> James

 Yeah, I like not overwriting ->special, and removing magic is always
good. :-)

 Hmmm, I have another proposal.  What do you think about replacing
scsi_request with scsi_cmnd.  I've been looking into it and it doesn't
seem to be too much work and it won't cause problems.  The only
bothering thing is that scsi_cmnd is limited resource and should be
returned to the pool ASAP.  AFAIK, all current users of
scsi_allocate_request() releses the scsi_request as soon as they're
finished, and we can make the requirement clear in the comment
(i.e. do not cache or hold on to scsi_cmnd).  This will remove the
scsi_request/cmnd dance and make scsi midlayer slimmer in other
places.  What do you think?

 Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-04-01  5:25     ` Tejun Heo
@ 2005-04-04 18:39       ` James Bottomley
  2005-04-05  6:19         ` Tejun Heo
  0 siblings, 1 reply; 42+ messages in thread
From: James Bottomley @ 2005-04-04 18:39 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Fri, 2005-04-01 at 14:25 +0900, Tejun Heo wrote:
>  Ah.. with later requeue path consolidation patches, all requests get
> their sense buffer cleared during requeueing, which, IMHO, is more
> logical.  Moving scsi_init_cmd_errh() should come after the patch.
> Sorry. :-)
> 
>  I'll make another take of this patchset (maybe subset) after issues
> are resolved.  I'll split and reorder relocation of scsi_init_cmd_errh
> then.

Thanks.  It would help me enormously if you explained what bugs you were
fixing at the top of each patch, and also only do patchsets that are
dependent on each other (I already have your serial_numer_at_timeout and
internal_timeout removal patches in the scsi-misc-2.6 tree).

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-04-04 18:39       ` James Bottomley
@ 2005-04-05  6:19         ` Tejun Heo
  2005-04-05 14:20           ` James Bottomley
  0 siblings, 1 reply; 42+ messages in thread
From: Tejun Heo @ 2005-04-05  6:19 UTC (permalink / raw)
  To: James Bottomley; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

  Hello, James.

James Bottomley wrote:
> On Fri, 2005-04-01 at 14:25 +0900, Tejun Heo wrote:
> 
>> Ah.. with later requeue path consolidation patches, all requests get
>>their sense buffer cleared during requeueing, which, IMHO, is more
>>logical.  Moving scsi_init_cmd_errh() should come after the patch.
>>Sorry. :-)
>>
>> I'll make another take of this patchset (maybe subset) after issues
>>are resolved.  I'll split and reorder relocation of scsi_init_cmd_errh
>>then.
> 
> 
> Thanks.  It would help me enormously if you explained what bugs you were
> fixing at the top of each patch,

  Well, I'll try harder.

 > and also only do patchsets that are
> dependent on each other (I already have your serial_numer_at_timeout and
> internal_timeout removal patches in the scsi-misc-2.6 tree).

  No problem.  Do you want me to do that now?  Or is it okay to do the 
next take after you review the request_fn rewrite patch?

  Thanks.

-- 
tejun


^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn()
  2005-04-05  6:19         ` Tejun Heo
@ 2005-04-05 14:20           ` James Bottomley
  0 siblings, 0 replies; 42+ messages in thread
From: James Bottomley @ 2005-04-05 14:20 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Jens Axboe, SCSI Mailing List, Linux Kernel

On Tue, 2005-04-05 at 15:19 +0900, Tejun Heo wrote:
>   No problem.  Do you want me to do that now?  Or is it okay to do the 
> next take after you review the request_fn rewrite patch?

Just on resubmit ... I think you're currently reworking the request_fn
patch based on Christoph's comments, so resend the sequence when you
have this.

Thanks,

James



^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2005-04-05 14:22 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-31  9:07 [PATCH scsi-misc-2.6 00/13] scsi: scsi_request_fn() rewrite & stuff Tejun Heo
2005-03-31  9:07 ` [PATCH scsi-misc-2.6 01/13] scsi: don't use blk_insert_request() for requeueing Tejun Heo
2005-03-31 10:12   ` Christoph Hellwig
2005-04-01  4:18     ` Tejun Heo
2005-03-31 17:53   ` James Bottomley
2005-04-01  5:01     ` Tejun Heo
2005-04-01 18:09       ` James Bottomley
2005-04-01 22:21         ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 02/13] scsi: don't turn on REQ_SPECIAL on sgtable allocation failure Tejun Heo
2005-03-31 17:53   ` James Bottomley
2005-04-01  5:14     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 03/13] scsi: remove unused scsi_cmnd->internal_timeout field Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 04/13] scsi: remove meaningless volatile qualifiers from structure definitions Tejun Heo
2005-03-31 10:11   ` Christoph Hellwig
2005-04-01  5:15     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 05/13] scsi: remove a timer race from scsi_queue_insert() and cleanup timer Tejun Heo
2005-03-31 10:13   ` Christoph Hellwig
2005-04-01  5:15     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 06/13] scsi: remove meaningless scsi_cmnd->serial_number_at_timeout field Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 07/13] scsi: move error handling out of scsi_init_io() into scsi_prep_fn() Tejun Heo
2005-04-01 18:23   ` James Bottomley
2005-04-01 23:07     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 08/13] scsi: move request preps in other places into prep_fn() Tejun Heo
2005-03-31 10:20   ` Christoph Hellwig
2005-04-01  5:20     ` Tejun Heo
2005-03-31 18:07   ` James Bottomley
2005-04-01  5:25     ` Tejun Heo
2005-04-04 18:39       ` James Bottomley
2005-04-05  6:19         ` Tejun Heo
2005-04-05 14:20           ` James Bottomley
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 09/13] scsi: in scsi_prep_fn(), remove bogus comments & clean up Tejun Heo
2005-03-31 10:22   ` Christoph Hellwig
2005-03-31 18:02   ` James Bottomley
2005-04-01  5:29     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 10/13] scsi: rewrite scsi_request_fn() Tejun Heo
2005-03-31 11:14   ` Christoph Hellwig
2005-04-01  5:44     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 11/13] scsi: add reprep arg to scsi_requeue_command() and make it public Tejun Heo
2005-03-31 10:32   ` Christoph Hellwig
2005-04-01  5:35     ` Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 12/13] scsi: replace scsi_queue_insert() with scsi_requeue_command() Tejun Heo
2005-03-31  9:08 ` [PATCH scsi-misc-2.6 13/13] scsi: consolidate scsi_cmd_retry() calls in scsi_error.c Tejun Heo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).