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
This commit is contained in:
Steven Hartland 2013-03-29 22:58:15 +00:00
parent ce7ad6640c
commit 5f83aee5e5
4 changed files with 55 additions and 9 deletions

View File

@ -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, void *arg)
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,

View File

@ -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

View File

@ -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 */

View File

@ -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, void *arg)
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;