From df02202cfb0d7df1c28225c7da0c3deb3698a730 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 18 Oct 2004 18:01:28 -0700 Subject: [PATCH] switchable and modular io schedulers This patch modularizes the io schedulers completely, allowing them to be modular. Additionally it enables online switching of io schedulers. See also http://lwn.net/Articles/102593/ . There's a scheduler file in the sysfs directory for the block device queue: axboe@router:/sys/block/hda/queue> ls iosched max_sectors_kb read_ahead_kb max_hw_sectors_kb nr_requests scheduler If you list the contents of the file, it will show available schedulers and the active one: axboe@router:/sys/block/hda/queue> cat scheduler [cfq] Lets load a few more. router:/sys/block/hda/queue # modprobe deadline-iosched router:/sys/block/hda/queue # modprobe as-iosched router:/sys/block/hda/queue # cat scheduler [cfq] deadline anticipatory Changing is done with router:/sys/block/hda/queue # echo deadline > scheduler router:/sys/block/hda/queue # cat scheduler cfq [deadline] anticipatory deadline is now the new active io scheduler for hda. Signed-off-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/blkdev.h | 10 ++++++--- include/linux/elevator.h | 55 +++++++++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 4efe45d1af7e..5e4a6ab84ecb 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -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 @@ struct request_list { 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 request_queue */ 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 @@ struct request_queue #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 blk_dump_rq_flags(struct request *, char *); 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); diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 27e8183f4776..95cdfb5bb790 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -22,9 +22,9 @@ typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int); typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); typedef int (elevator_init_fn) (request_queue_t *, elevator_t *); -typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *); +typedef void (elevator_exit_fn) (elevator_t *); -struct elevator_s +struct elevator_ops { elevator_merge_fn *elevator_merge_fn; elevator_merged_fn *elevator_merged_fn; @@ -48,12 +48,32 @@ struct elevator_s elevator_init_fn *elevator_init_fn; elevator_exit_fn *elevator_exit_fn; +}; - void *elevator_data; +#define ELV_NAME_MAX (16) - struct kobject kobj; +/* + * identifies an elevator type, such as AS or deadline + */ +struct elevator_type +{ + struct list_head list; + struct elevator_ops ops; + struct elevator_type *elevator_type; struct kobj_type *elevator_ktype; - const char *elevator_name; + char elevator_name[ELV_NAME_MAX]; + struct module *elevator_owner; +}; + +/* + * each queue has an elevator_queue assoicated with it + */ +struct elevator_queue +{ + struct elevator_ops *ops; + void *elevator_data; + struct kobject kobj; + struct elevator_type *elevator_type; }; /* @@ -79,28 +99,19 @@ extern int elv_set_request(request_queue_t *, struct request *, int); extern void elv_put_request(request_queue_t *, struct request *); /* - * noop I/O scheduler. always merges, always inserts new request at tail - */ -extern elevator_t elevator_noop; - -/* - * deadline i/o scheduler. uses request time outs to prevent indefinite - * starvation - */ -extern elevator_t iosched_deadline; - -/* - * anticipatory I/O scheduler + * io scheduler registration */ -extern elevator_t iosched_as; +extern int elv_register(struct elevator_type *); +extern void elv_unregister(struct elevator_type *); /* - * completely fair queueing I/O scheduler + * io scheduler sysfs switching */ -extern elevator_t iosched_cfq; +extern ssize_t elv_iosched_show(request_queue_t *, char *); +extern ssize_t elv_iosched_store(request_queue_t *, const char *, size_t); -extern int elevator_init(request_queue_t *, elevator_t *); -extern void elevator_exit(request_queue_t *); +extern int elevator_init(request_queue_t *, char *); +extern void elevator_exit(elevator_t *); extern int elv_rq_merge_ok(struct request *, struct bio *); extern int elv_try_merge(struct request *, struct bio *); extern int elv_try_last_merge(request_queue_t *, struct bio *); -- cgit v1.2.3