modular io schedulers with online switching
Subsystems (3)
PATCH 1/1 modular io schedulers with online switching
Hi,
This patch implements fully modular io schedulers and enables online switching between them. It adds a new sysfs entry in the block path that shows the current one in brackets and the other ones along side it:
bart:/sys/block/sda/queue # cat scheduler
anticipatory deadline [cfq]
cfq is selected here. I built noop as a module here, if I load it:
bart:/sys/block/sda/queue # modprobe noop-iosched
bart:/sys/block/sda/queue # cat scheduler
anticipatory deadline [cfq] noop
it shows up as well. Switching is just as simple, you simply echo the desired scheduler into that file:
bart:/sys/block/sda/queue # echo anticipatory > scheduler bart:/sys/block/sda/queue # cat scheduler [anticipatory] deadline cfq noop
Most of the patch is making q->elevator allocated instead of embedded inside the queue, and splitting elevator_t into two parts - one for the elvator_type (noop, deadline, etc) and elevator_queue that's an instance of that associated with a given queue.
With the io schedulers fully modular, it is possible to add a new io scheduler type without touching the core kernel at all. elv_register() and elv_unregister() register a new io scheduler with the elevator core.
Remember to build at least 1 io scheduler into the kernel, they can't all be modules :-)
Patch is against current BK.
===== drivers/block/Kconfig.iosched 1.3 vs edited =====
drivers/block/Kconfig.iosched +4 -4
@@ -1,5 +1,5 @@ config IOSCHED_NOOP - bool "No-op I/O scheduler" if EMBEDDED + tristate "No-op I/O scheduler" default y ---help--- The no-op I/O scheduler is a minimal scheduler that does basic merging
@@ -9,7 +9,7 @@ the kernel. config IOSCHED_AS - bool "Anticipatory I/O scheduler" if EMBEDDED + tristate "Anticipatory I/O scheduler" default y ---help--- The anticipatory I/O scheduler is the default disk scheduler. It is
@@ -18,7 +18,7 @@ slower in some cases especially some database loads. config IOSCHED_DEADLINE - bool "Deadline I/O scheduler" if EMBEDDED + tristate "Deadline I/O scheduler" default y ---help--- The deadline I/O scheduler is simple and compact, and is often as
@@ -28,7 +28,7 @@ anticipatory I/O scheduler and so is a good choice. config IOSCHED_CFQ - bool "CFQ I/O scheduler" if EMBEDDED + tristate "CFQ I/O scheduler" default y ---help--- The CFQ I/O scheduler tries to distribute bandwidth equally
===== drivers/block/as-iosched.c 1.38 vs edited =====
drivers/block/as-iosched.c +56 -43
200 lines not on this page · raw message
===== drivers/block/cfq-iosched.c 1.8 vs edited =====
drivers/block/cfq-iosched.c +70 -39
207 lines not on this page · raw message
===== drivers/block/deadline-iosched.c 1.29 vs edited =====
drivers/block/deadline-iosched.c +50 -36
170 lines not on this page · raw message
===== drivers/block/elevator.c 1.58 vs edited =====
drivers/block/elevator.c +217 -52
430 lines not on this page · raw message
===== drivers/block/ll_rw_blk.c 1.271 vs edited =====
drivers/block/ll_rw_blk.c +89 -35
225 lines not on this page · raw message
===== drivers/block/noop-iosched.c 1.3 vs edited =====
drivers/block/noop-iosched.c +21 -7
@@ -83,12 +83,26 @@return NULL ; } -elevator_t elevator_noop = { - .elevator_merge_fn = elevator_noop_merge, - .elevator_merge_req_fn = elevator_noop_merge_requests, - .elevator_next_req_fn = elevator_noop_next_request, - .elevator_add_req_fn = elevator_noop_add_request, - .elevator_name ="noop" , +static struct elevator_type elevator_noop = { + .ops = { + .elevator_merge_fn = elevator_noop_merge, + .elevator_merge_req_fn = elevator_noop_merge_requests, + .elevator_next_req_fn = elevator_noop_next_request, + .elevator_add_req_fn = elevator_noop_add_request, + }, + .elevator_name ="noop" , + .elevator_owner =THIS_MODULE , }; -EXPORT_SYMBOL (elevator_noop); +int noop_init (void ) +{ +return elv_register (&elevator_noop); +} + +void noop_exit (void ) +{ +elv_unregister (&elevator_noop); +} + +module_init (noop_init); +module_exit (noop_exit);
===== drivers/s390/block/dasd.c 1.77 vs edited =====
drivers/s390/block/dasd.c +2 -2
@@ -1595,8 +1595,8 @@ device->request_queue->queuedata = device;#if 0 -elevator_exit (device->request_queue); - rc =elevator_init (device->request_queue, &elevator_noop); +elevator_exit (device->request_queue->elevator); + rc =elevator_init (device->request_queue,"noop" );if (rc) {blk_cleanup_queue (device->request_queue);return rc;
===== drivers/s390/char/tape_block.c 1.12 vs edited =====
drivers/s390/char/tape_block.c +2 -2
@@ -225,8 +225,8 @@if (!blkdat->request_queue)return -ENOMEM ; -elevator_exit (blkdat->request_queue); - rc =elevator_init (blkdat->request_queue, &elevator_noop); +elevator_exit (blkdat->request_queue->elevator); + rc =elevator_init (blkdat->request_queue,"noop" );if (rc) goto cleanup_queue;
===== include/linux/blkdev.h 1.152 vs edited =====
include/linux/blkdev.h +7 -3
@@ -19,8 +19,8 @@struct request_queue ;typedef struct request_queue request_queue_t ; -struct elevator_s ; -typedef struct elevator_s elevator_t ; +struct elevator_queue ; +typedef struct elevator_queue elevator_t ;struct request_pm_state ;#define BLKDEV_MIN_RQ 4
@@ -80,6 +80,7 @@int count[2 ];mempool_t *rq_pool;wait_queue_head_t wait[2 ]; +wait_queue_head_t drain; };#define BLK_MAX_CDB 16
@@ -279,7 +280,7 @@*/ struct list_head queue_head;struct request *last_merge; -elevator_t elevator; +elevator_t *elevator;/* * the queue request freelist, one for reads and one for writes
@@ -381,6 +382,7 @@#define QUEUE_FLAG_REENTER 6/* Re-entrancy avoidance */ #define QUEUE_FLAG_PLUGGED 7/* queue is plugged */ #define QUEUE_FLAG_ORDERED 8/* supports ordered writes */ +#define QUEUE_FLAG_DRAIN 9/* draining queue for sched switch */ #define blk_queue_plugged (q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)#define blk_queue_tagged (q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -617,6 +619,8 @@extern void generic_unplug_device (request_queue_t *);extern void __generic_unplug_device (request_queue_t *);extern long nr_blockdev_pages (void ); +extern void blk_wait_queue_drained (request_queue_t *); +extern void blk_finish_queue_drain (request_queue_t *);int blk_get_queue (request_queue_t *);request_queue_t *blk_alloc_queue (int );
===== include/linux/elevator.h 1.31 vs edited =====
include/linux/elevator.h +33 -22
82 lines not on this page · raw message
Signature · 1 line
Jens Axboe