This patch adds per disk queue functionality. It seems that the 2.6 kernel 
expects a queue per disk. If you have multiple logical drives on a controller 
all of the queues actually point back to the same queue. If a drive is deleted 
it blows us out of the water.
We hold the lock during any queue operations and have added what we call a
"fair-enough" algorithm to prevent starving out any drive.

Please consider this for inclusion.

Signed-off-by: Mike Miller <[EMAIL PROTECTED]>

 cciss.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++----
 cciss.h |    5 +++++
 2 files changed, 53 insertions(+), 4 deletions(-)
----------------------------------------------------------------------------
diff -burNp lx2611-p002/drivers/block/cciss.c lx2611-p003/drivers/block/cciss.c
--- lx2611-p002/drivers/block/cciss.c   2005-03-08 16:50:47.149175280 -0600
+++ lx2611-p003/drivers/block/cciss.c   2005-03-08 17:17:50.148441888 -0600
@@ -2090,6 +2090,9 @@ static void do_cciss_request(request_que
        drive_info_struct *drv;
        int i, dir;
 
+       /* We call start_io here in case there is a command waiting on the
+        * queue that has not been sent.
+       */
        if (blk_queue_plugged(q))
                goto startio;
 
@@ -2178,6 +2181,9 @@ queue:
 full:
        blk_stop_queue(q);
 startio:
+       /* We will already have the driver lock here so not need
+        * to lock it.
+       */
        start_io(h);
 }
 
@@ -2187,7 +2193,8 @@ static irqreturn_t do_cciss_intr(int irq
        CommandList_struct *c;
        unsigned long flags;
        __u32 a, a1;
-
+       int j;
+       int start_queue = h->next_to_run;
 
        /* Is this interrupt for us? */
        if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))
@@ -2234,13 +2241,50 @@ static irqreturn_t do_cciss_intr(int irq
                }
        }
 
-       /*
-        * See if we can queue up some more IO
+       /* check to see if we have maxed out the number of commands that can
+        * be placed on the queue.  If so then exit.  We do this check here
+        * in case the interrupt we serviced was from an ioctl and did not
+        * free any new commands.
         */
-       blk_start_queue(h->queue);
+       if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+               goto cleanup;
+ 
+       /* We have room on the queue for more commands.  Now we need to queue
+        * them up.  We will also keep track of the next queue to run so
+        * that every queue gets a chance to be started first.
+       */
+       for (j=0; j < NWD; j++){
+               int curr_queue = (start_queue + j) % NWD;
+               /* make sure the disk has been added and the drive is real
+                * because this can be called from the middle of init_one.
+               */
+               if(!(h->gendisk[curr_queue]->queue) || 
+                                  !(h->drv[curr_queue].heads))
+                       continue;
+               blk_start_queue(h->gendisk[curr_queue]->queue);
+ 
+               /* check to see if we have maxed out the number of commands 
+                * that can be placed on the queue.  
+               */
+               if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+               {
+                       if (curr_queue == start_queue){
+                               h->next_to_run = (start_queue + 1) % NWD;
+                               goto cleanup;
+                       } else {
+                               h->next_to_run = curr_queue;
+                               goto cleanup;
+       }
+               } else {
+                       curr_queue = (curr_queue + 1) % NWD;
+               }
+       }
+ 
+cleanup:
        spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
        return IRQ_HANDLED;
 }
+
 /* 
  *  We cannot read the structure directly, for portablity we must use 
  *   the io functions.
Files lx2611-p002/drivers/block/.cciss.c.rej.swp and 
lx2611-p003/drivers/block/.cciss.c.rej.swp differ
diff -burNp lx2611-p002/drivers/block/cciss.h lx2611-p003/drivers/block/cciss.h
--- lx2611-p002/drivers/block/cciss.h   2005-03-08 16:50:47.150175128 -0600
+++ lx2611-p003/drivers/block/cciss.h   2005-03-08 17:03:04.279114496 -0600
@@ -84,6 +84,11 @@ struct ctlr_info 
        int                     nr_frees; 
        int                     busy_configuring;
 
+       /* This element holds the zero based queue number of the last
+        * queue to be started.  It is used for fairness.
+       */
+       int                     next_to_run;
+
        // Disk structures we need to pass back
        struct gendisk   *gendisk[NWD];
 #ifdef CONFIG_CISS_SCSI_TAPE
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to