Index: linux/block/genhd.c =================================================================== --- linux.orig/block/genhd.c +++ linux/block/genhd.c @@ -30,6 +30,8 @@ static struct blk_major_name { char name[16]; } *major_names[BLKDEV_MAJOR_HASH_SIZE]; +LIST_HEAD(gendisks); + /* index in the above - for now: assume no multimajor ranges */ static inline int major_to_index(int major) { @@ -395,19 +397,22 @@ static ssize_t disk_stats_read(struct ge jiffies_to_msecs(disk_stat_read(disk, io_ticks)), jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); } + +#ifdef CONFIG_FINGERPRINTING static ssize_t disk_fp_read(struct gendisk * disk, char *page) { - return sprintf(page, "reads: %llx\n" - "writes: %llx\n" - "head_pos: %llx\n" - "avg_dist: %llx\n" - "avg_size: %llx\n", + return sprintf(page, "reads: %lld\n" + "writes: %lld\n" + "head_pos: %lld\n" + "avg_dist: %lld\n" + "avg_size: %lld\n", (unsigned long long)disk->fp_ss->reads, (unsigned long long)disk->fp_ss->writes, (unsigned long long)disk->fp_ss->head_pos, (unsigned long long)disk->fp_ss->avg_dist, (unsigned long long)disk->fp_ss->avg_size); } +#endif static struct disk_attribute disk_attr_uevent = { .attr = {.name = "uevent", .mode = S_IWUSR }, @@ -433,10 +438,13 @@ static struct disk_attribute disk_attr_s .attr = {.name = "stat", .mode = S_IRUGO }, .show = disk_stats_read }; + +#ifdef CONFIG_FINGERPRINTING static struct disk_attribute disk_attr_fp = { .attr = {.name = "fp", .mode = S_IRUGO }, .show = disk_fp_read }; +#endif #ifdef CONFIG_FAIL_MAKE_REQUEST @@ -476,7 +484,9 @@ static struct attribute * default_attrs[ #ifdef CONFIG_FAIL_MAKE_REQUEST &disk_attr_fail.attr, #endif - &disk_attr_fp.attr, +#ifdef CONFIG_FINGERPRINTING + &disk_attr_fp.attr, +#endif NULL, }; @@ -485,6 +495,7 @@ static void disk_release(struct kobject struct gendisk *disk = to_disk(kobj); kfree(disk->random); kfree(disk->part); + list_del(&disk->gendisks); free_disk_stats(disk); kfree(disk); } @@ -685,8 +696,9 @@ struct gendisk *alloc_disk_node(int mino kobj_set_kset_s(disk,block_subsys); kobject_init(&disk->kobj); rand_initialize_disk(disk); + list_add_tail(&disk->gendisks, &gendisks); INIT_WORK(&disk->async_notify, media_change_notify_thread); } disk->fp_ss = kmalloc(sizeof(struct fp_snapshot), GFP_KERNEL); Index: linux/block/ll_rw_blk.c =================================================================== --- linux.orig/block/ll_rw_blk.c +++ linux/block/ll_rw_blk.c @@ -21,6 +21,7 @@ #include #include #include /* for max_pfn/max_low_pfn */ +#include #include #include #include @@ -2694,6 +2695,143 @@ static inline void add_request(request_q __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } +#if defined(CONFIG_GENETIC_IOSCHED_AS) || \ + defined(CONFIG_GENETIC_IOSCHED_DEADLINE) || \ + defined(CONFIG_GENETIC_IOSCHED_CFQ) +extern struct list_head gendisks; + +void disk_stats_snapshot(phenotype_t * pt) +{ + struct list_head * d; + struct gendisk *disk; + struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)pt->child_ranking[0]->stats_snapshot; + + memset(ss, 0, sizeof(struct disk_stats_snapshot)); + + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + disk_round_stats(disk); + + ss->reads += disk_stat_read(disk, ios[READ]); + ss->writes += disk_stat_read(disk, ios[WRITE]); + ss->read_sectors += disk_stat_read(disk, sectors[READ]); + ss->write_sectors += disk_stat_read(disk, sectors[WRITE]); + ss->time_in_queue += disk_stat_read(disk, time_in_queue); + } +} + +long long disk_num_ops_calc_fitness(genetic_child_t * child) +{ + struct list_head * d; + struct gendisk *disk; + struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; + long long reads = 0; + long long writes = 0; + + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + disk_round_stats(disk); + + reads += disk_stat_read(disk, ios[READ]); + writes += disk_stat_read(disk, ios[WRITE]); + } + + reads -= ss->reads; + writes -= ss->writes; + + return reads + writes; +} + +long long disk_throughput_calc_fitness(genetic_child_t * child) +{ + struct list_head * d; + struct gendisk *disk; + struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; + long long read_sectors = 0; + long long write_sectors = 0; + + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + disk_round_stats(disk); + + read_sectors += disk_stat_read(disk, sectors[READ]); + write_sectors += disk_stat_read(disk, sectors[WRITE]); + } + + read_sectors -= ss->read_sectors; + write_sectors -= ss->write_sectors; + + return read_sectors + write_sectors; +} + +long long disk_latency_calc_fitness(genetic_child_t * child) +{ + struct list_head * d; + struct gendisk *disk; + struct disk_stats_snapshot * ss = (struct disk_stats_snapshot *)child->stats_snapshot; + long long time_in_queue = 0; + + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + disk_round_stats(disk); + + time_in_queue += disk_stat_read(disk, time_in_queue); + } + + time_in_queue = -(time_in_queue - ss->time_in_queue); + + return time_in_queue; +} + +#ifdef CONFIG_FINGERPRINTING + +void disk_update_fingerprint(phenotype_t * pt) +{ + struct list_head * d; + struct gendisk *disk; + + BUG_ON(!pt->fp_ss); + + /* tally up all the other disk snapshots */ + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + consolidate_fp_snapshot(pt->fp_ss, disk->fp_ss); + + /* reset it for the next generation */ + reset_fp_snapshot(disk->fp_ss); + } + +} + +void disk_get_fingerprint(phenotype_t * pt) +{ + struct list_head * d; + struct gendisk *disk; + + BUG_ON(!pt->fp_ss); + + /* tally up all the other disk snapshots */ + list_for_each(d, &gendisks) { + disk = list_entry(d, struct gendisk, gendisks); + + consolidate_fp_snapshot(pt->fp_ss, disk->fp_ss); + + /* reset it for the next generation */ + reset_fp_snapshot(disk->fp_ss); + } + + calc_fp(pt->fp, pt->fp_ss); +} + +#endif /* CONFIG_FINGERPRINTING */ + +#endif + /* * disk_round_stats() - Round off the performance stats on a struct * disk_stats. Index: linux/include/linux/genhd.h =================================================================== --- linux.orig/include/linux/genhd.h +++ linux/include/linux/genhd.h @@ -134,6 +134,7 @@ struct gendisk { atomic_t sync_io; /* RAID */ unsigned long stamp; int in_flight; + struct list_head gendisks; #ifdef CONFIG_SMP struct disk_stats *dkstats; #else Index: linux/include/linux/blkdev.h =================================================================== --- linux.orig/include/linux/blkdev.h +++ linux/include/linux/blkdev.h @@ -861,6 +861,20 @@ void kblockd_flush_work(struct work_stru MODULE_ALIAS("block-major-" __stringify(major) "-*") +#if defined(CONFIG_GENETIC_IOSCHED_AS) || \ + defined(CONFIG_GENETIC_IOSCHED_DEADLINE) || \ + defined(CONFIG_GENETIC_IOSCHED_CFQ) + +struct disk_stats_snapshot +{ + unsigned long reads; + unsigned long writes; + unsigned long read_sectors; + unsigned long write_sectors; + unsigned long time_in_queue; +}; +#endif /* CONFIG_GENETIC_IOSCHED_AS || CONFIG_GENETIC_IOSCHED_CFQ */ + #else /* CONFIG_BLOCK */ /* * stubs for when the block layer is configured out