--- diff -puN drivers/block/Kconfig.iosched~genetic-deadline-sched drivers/block/Kconfig.iosched --- linux-2.6.9/drivers/block/Kconfig.iosched~genetic-deadline-sched Thu Oct 21 14:45:00 2004 +++ linux-2.6.9-moilanen/drivers/block/Kconfig.iosched Thu Oct 21 14:45:00 2004 @@ -43,3 +43,12 @@ config GENETIC_IOSCHED_AS This will use a genetic algorithm to tweak the tunables of the anticipatory scheduler autonomically and will adapt tunables depending on the present workload. + +config GENETIC_IOSCHED_DEADLINE + bool "Genetic Deadline I/O scheduler (EXPERIMENTAL)" + depends on IOSCHED_DEADLINE && GENETIC_LIB && EXPERIMENTAL + default n + ---help--- + This will use a genetic algorithm to tweak the tunables of the + deadline scheduler autonomically and will adapt tunables + depending on the present workload. diff -puN drivers/block/deadline-iosched.c~genetic-deadline-sched drivers/block/deadline-iosched.c --- linux-2.6.9/drivers/block/deadline-iosched.c~genetic-deadline-sched Thu Oct 21 14:45:00 2004 +++ linux-2.6.9-moilanen/drivers/block/deadline-iosched.c Thu Oct 21 14:45:00 2004 @@ -17,15 +17,21 @@ #include #include #include +#include /* * See Documentation/deadline-iosched.txt */ -static int read_expire = HZ / 2; /* max time before a read is submitted. */ -static int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ -static int writes_starved = 2; /* max times reads can starve a write */ -static int fifo_batch = 16; /* # of sequential requests treated as one - by the above parameters. For throughput. */ +#define default_read_expire (HZ / 2) +#define default_write_expire (5 * HZ) +#define default_writes_starved 2 +#define default_fifo_batch 16 + +static int read_expire = default_read_expire; /* max time before a read is submitted. */ +static int write_expire = default_write_expire; /* ditto for writes, these limits are SOFT! */ +static int writes_starved = default_writes_starved; /* max times reads can starve a write */ +static int fifo_batch = default_fifo_batch; /* # of sequential requests treated as one + by the above parameters. For throughput. */ static const int deadline_hash_shift = 5; #define DL_HASH_BLOCK(sec) ((sec) >> 3) @@ -65,6 +71,10 @@ struct deadline_data { int front_merges; mempool_t *drq_pool; + +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + struct list_head data_list; +#endif }; /* @@ -98,6 +108,50 @@ static kmem_cache_t *drq_pool; #define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + +static void deadline_create_child(genetic_child_t * child); +static void deadline_set_child_genes(void * in_genes); +static void deadline_calc_fitness(genetic_child_t * child); + +struct genetic_ops deadline_genetic_ops = { + .create_child = deadline_create_child, + .set_child_genes = deadline_set_child_genes, + .calc_fitness = deadline_calc_fitness, + .combine_genes = genetic_generic_combine_genes, + .mutate_child = genetic_generic_mutate_child, +}; + +#define DEADLINE_NUM_GENES 4 +#define DEADLINE_NUM_CHILDREN 8 + +struct deadline_genes { + unsigned long read_expire; + unsigned long write_expire; + unsigned long writes_starved; + unsigned long fifo_batch; +}; + +long deadline_genes_range[DEADLINE_NUM_GENES] = { + default_read_expire, + default_write_expire, + default_writes_starved, + default_fifo_batch +}; + +long deadline_genes_default[DEADLINE_NUM_GENES] = { + default_read_expire, + default_write_expire, + default_writes_starved, + default_fifo_batch +}; + +extern void disk_stats_snapshot(void); +extern unsigned long disk_calc_fitness(void); + +LIST_HEAD(deadline_data_list); +#endif + /* * the back merge hash support functions */ @@ -695,6 +749,11 @@ static void deadline_exit(request_queue_ BUG_ON(!list_empty(&dd->fifo_list[WRITE])); mempool_destroy(dd->drq_pool); + +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + list_del(&dd->data_list); +#endif + kfree(dd->hash); kfree(dd); } @@ -743,6 +802,10 @@ static int deadline_init(request_queue_t dd->front_merges = 1; dd->fifo_batch = fifo_batch; e->elevator_data = dd; + +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + list_add_tail(&dd->data_list, &deadline_data_list); +#endif return 0; } @@ -908,12 +971,21 @@ struct kobj_type deadline_ktype = { static int __init deadline_slab_setup(void) { + int rc; + drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq), 0, 0, NULL, NULL); if (!drq_pool) panic("deadline: can't init slab pool\n"); +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + rc = genetic_init(0, &deadline_genetic_ops, DEADLINE_NUM_CHILDREN, 2 * HZ, "deadline-ioscheduler"); + if (rc) + panic("deadline: failed to init genetic lib"); +#endif + + return 0; } @@ -939,3 +1011,62 @@ elevator_t iosched_deadline = { }; EXPORT_SYMBOL(iosched_deadline); + +#ifdef CONFIG_GENETIC_IOSCHED_DEADLINE + +/* need to create the genes for the child */ +static void deadline_create_child(genetic_child_t * child) +{ + int i; + static int child_num = 1; + int range_incr; + unsigned long * genes; + + BUG_ON(!child); + + child->genes = (void *)kmalloc(sizeof(struct deadline_genes), GFP_KERNEL); + if (!child->genes) + panic("deadline_create_child: error mallocing space"); + + for (i = 0; i < DEADLINE_NUM_GENES; i++) { + genes = (unsigned long *)child->genes; + range_incr = deadline_genes_range[i] / DEADLINE_NUM_CHILDREN; + if (range_incr) + genes[i] = deadline_genes_default[i] + + ((range_incr * child_num) - (deadline_genes_default[i] / 2)); + else + genes[i] = deadline_genes_default[i]; + } + + child->genes_default = deadline_genes_default; + child->genes_range = deadline_genes_range; + child->num_genes = DEADLINE_NUM_GENES; + + child_num++; +} + +static void deadline_set_child_genes(void * in_genes) +{ + struct deadline_genes * genes = (struct deadline_genes *)in_genes; + struct list_head * d; + struct deadline_data * dd; + + list_for_each(d, &deadline_data_list) { + dd = list_entry(d, struct deadline_data, data_list); + dd->fifo_expire[READ] = genes->read_expire; + dd->fifo_expire[WRITE] = genes->write_expire; + dd->writes_starved = genes->writes_starved; + dd->fifo_batch = genes->fifo_batch; + } + + /* Set a mark for the start of this child to help calculate + fitness */ + disk_stats_snapshot(); +} + +static void deadline_calc_fitness(genetic_child_t * child) +{ + child->fitness = disk_calc_fitness(); +} + +#endif _