Author: smh
Date: Fri Mar 29 22:58:15 2013
New Revision: 248922
URL: http://svnweb.freebsd.org/changeset/base/248922

Log:
  Adds the ability to enable / disable sorting of BIO requests queued within
  CAM. This can significantly improve performance particularly for SSDs
  which don't suffer from seek latencies.
  
  The sysctl / tunable kern.cam.sort_io_queues provides the systems default
  setting where:-
  0 = queued BIOs are NOT sorted
  1 = queued BIOs are sorted (default)
  
  Each device gets its own sysctl kern.cam.<type>.<id>.sort_io_queue
  Valid values are:-
  -1 = use system default (default)
  0 = queued BIOs are NOT sorted
  1 = queued BIOs are sorted
  
  Note: Additional patch will look to add automatic use of none sorted queues
  for none rotating media e.g. SSD's
  
  Reviewed by:  scottl
  Approved by:  pjd (mentor)
  MFC after:    2 weeks

Modified:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/cam.c
  head/sys/cam/cam.h
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c   Fri Mar 29 22:05:26 2013        (r248921)
+++ head/sys/cam/ata/ata_da.c   Fri Mar 29 22:58:15 2013        (r248922)
@@ -130,6 +130,7 @@ struct ada_softc {
        ada_state state;
        ada_flags flags;        
        ada_quirks quirks;
+       int      sort_io_queue;
        int      ordered_tag_count;
        int      outstanding_cmds;
        int      trim_max_ranges;
@@ -449,6 +450,8 @@ static void         adaresume(void *arg);
                 softc->read_ahead : ada_read_ahead)
 #define        ADA_WC  (softc->write_cache >= 0 ? \
                 softc->write_cache : ada_write_cache)
+#define        ADA_SIO (softc->sort_io_queue >= 0 ? \
+                softc->sort_io_queue : cam_sort_io_queues)
 
 /*
  * Most platforms map firmware geometry to actual, but some don't.  If
@@ -670,10 +673,17 @@ adastrategy(struct bio *bp)
         * Place it in the queue of disk activities for this disk
         */
        if (bp->bio_cmd == BIO_DELETE &&
-           (softc->flags & ADA_FLAG_CAN_TRIM))
-               bioq_disksort(&softc->trim_queue, bp);
-       else
-               bioq_disksort(&softc->bio_queue, bp);
+           (softc->flags & ADA_FLAG_CAN_TRIM)) {
+               if (ADA_SIO)
+                   bioq_disksort(&softc->trim_queue, bp);
+               else
+                   bioq_insert_tail(&softc->trim_queue, bp);
+       } else {
+               if (ADA_SIO)
+                   bioq_disksort(&softc->bio_queue, bp);
+               else
+                   bioq_insert_tail(&softc->bio_queue, bp);
+       }
 
        /*
         * Schedule ourselves for performing the work.
@@ -999,6 +1009,10 @@ adasysctlinit(void *context, int pending
        SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
                OID_AUTO, "write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE,
                &softc->write_cache, 0, "Enable disk write cache.");
+       SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
+               OID_AUTO, "sort_io_queue", CTLFLAG_RW | CTLFLAG_MPSAFE,
+               &softc->sort_io_queue, 0,
+               "Sort IO queue to try and optimise disk access patterns");
 #ifdef ADA_TEST_FAILURE
        /*
         * Add a 'door bell' sysctl which allows one to set it from userland
@@ -1134,6 +1148,7 @@ adaregister(struct cam_periph *periph, v
        snprintf(announce_buf, sizeof(announce_buf),
            "kern.cam.ada.%d.write_cache", periph->unit_number);
        TUNABLE_INT_FETCH(announce_buf, &softc->write_cache);
+       softc->sort_io_queue = -1;
        adagetparams(periph, cgd);
        softc->disk = disk_alloc();
        softc->disk->d_devstat = devstat_new_entry(periph->periph_name,

Modified: head/sys/cam/cam.c
==============================================================================
--- head/sys/cam/cam.c  Fri Mar 29 22:05:26 2013        (r248921)
+++ head/sys/cam/cam.c  Fri Mar 29 22:58:15 2013        (r248922)
@@ -110,6 +110,15 @@ const int num_cam_status_entries =
 
 #ifdef _KERNEL
 SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem");
+
+#ifndef CAM_DEFAULT_SORT_IO_QUEUES
+#define CAM_DEFAULT_SORT_IO_QUEUES 1
+#endif
+
+int cam_sort_io_queues = CAM_DEFAULT_SORT_IO_QUEUES;
+TUNABLE_INT("kern.cam.sort_io_queues", &cam_sort_io_queues);
+SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN,
+    &cam_sort_io_queues, 0, "Sort IO queues to try and optimise disk access 
patterns");
 #endif
 
 void

Modified: head/sys/cam/cam.h
==============================================================================
--- head/sys/cam/cam.h  Fri Mar 29 22:05:26 2013        (r248921)
+++ head/sys/cam/cam.h  Fri Mar 29 22:58:15 2013        (r248922)
@@ -228,6 +228,9 @@ struct cam_status_entry
 
 extern const struct cam_status_entry cam_status_table[];
 extern const int num_cam_status_entries;
+#ifdef _KERNEL
+extern int cam_sort_io_queues;
+#endif
 union ccb;
 
 #ifdef SYSCTL_DECL     /* from sysctl.h */

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c Fri Mar 29 22:05:26 2013        (r248921)
+++ head/sys/cam/scsi/scsi_da.c Fri Mar 29 22:58:15 2013        (r248922)
@@ -145,6 +145,7 @@ struct da_softc {
        da_state state;
        da_flags flags; 
        da_quirks quirks;
+       int      sort_io_queue;
        int      minimum_cmd_size;
        int      error_inject;
        int      ordered_tag_count;
@@ -903,6 +904,8 @@ static timeout_t    damediapoll;
 #define        DA_DEFAULT_SEND_ORDERED 1
 #endif
 
+#define DA_SIO (softc->sort_io_queue >= 0 ? \
+    softc->sort_io_queue : cam_sort_io_queues)
 
 static int da_poll_period = DA_DEFAULT_POLL_PERIOD;
 static int da_retry_count = DA_DEFAULT_RETRY;
@@ -1140,10 +1143,15 @@ dastrategy(struct bio *bp)
        if (bp->bio_cmd == BIO_DELETE) {
                if (bp->bio_bcount == 0)
                        biodone(bp);
-               else
+               else if (DA_SIO)
                        bioq_disksort(&softc->delete_queue, bp);
-       } else
+               else
+                       bioq_insert_tail(&softc->delete_queue, bp);
+       } else if (DA_SIO) {
                bioq_disksort(&softc->bio_queue, bp);
+       } else {
+               bioq_insert_tail(&softc->bio_queue, bp);
+       }
 
        /*
         * Schedule ourselves for performing the work.
@@ -1504,6 +1512,9 @@ dasysctlinit(void *context, int pending)
                OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
                &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
                "Minimum CDB size");
+       SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
+               OID_AUTO, "sort_io_queue", CTLFLAG_RW, &softc->sort_io_queue, 0,
+               "Sort IO queue to try and optimise disk access patterns");
 
        SYSCTL_ADD_INT(&softc->sysctl_ctx,
                       SYSCTL_CHILDREN(softc->sysctl_tree),
@@ -1651,6 +1662,7 @@ daregister(struct cam_periph *periph, vo
                softc->flags |= DA_FLAG_PACK_REMOVABLE;
        softc->unmap_max_ranges = UNMAP_MAX_RANGES;
        softc->unmap_max_lba = 1024*1024*2;
+       softc->sort_io_queue = -1;
 
        periph->softc = softc;
 
@@ -2133,9 +2145,16 @@ cmd6workaround(union ccb *ccb)
                        dadeletemethodset(softc, DA_DELETE_DISABLE);
                } else
                        dadeletemethodset(softc, DA_DELETE_DISABLE);
-               while ((bp = bioq_takefirst(&softc->delete_run_queue))
-                   != NULL)
-                       bioq_disksort(&softc->delete_queue, bp);
+
+               if (DA_SIO) {
+                       while ((bp = bioq_takefirst(&softc->delete_run_queue))
+                           != NULL)
+                               bioq_disksort(&softc->delete_queue, bp);
+               } else {
+                       while ((bp = bioq_takefirst(&softc->delete_run_queue))
+                           != NULL)
+                               bioq_insert_tail(&softc->delete_queue, bp);
+               }
                bioq_insert_tail(&softc->delete_queue,
                    (struct bio *)ccb->ccb_h.ccb_bp);
                ccb->ccb_h.ccb_bp = NULL;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to