read/write speed of Flash based storage usually is different. For example, in my SSD maxium thoughput of read is about 3 times faster than that of write. Add a scale to differenate read and write. Also add a tunable, so user can assign different scale for read and write. By default, the scale is 1:1, which means the scale is a noop. Signed-off-by: Shaohua Li --- block/fiops-iosched.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) Index: linux/block/fiops-iosched.c =================================================================== --- linux.orig/block/fiops-iosched.c 2012-01-18 14:33:32.000000000 +0800 +++ linux/block/fiops-iosched.c 2012-01-18 14:33:51.000000000 +0800 @@ -15,6 +15,9 @@ #define VIOS_SCALE_SHIFT 10 #define VIOS_SCALE (1 << VIOS_SCALE_SHIFT) +#define VIOS_READ_SCALE (1) +#define VIOS_WRITE_SCALE (1) + struct fiops_rb_root { struct rb_root rb; struct rb_node *left; @@ -33,6 +36,9 @@ struct fiops_data { unsigned int in_flight[2]; struct work_struct unplug_work; + + unsigned int read_scale; + unsigned int write_scale; }; struct fiops_ioc { @@ -280,7 +286,12 @@ static void fiops_remove_request(struct static u64 fiops_scaled_vios(struct fiops_data *fiopsd, struct fiops_ioc *ioc, struct request *rq) { - return VIOS_SCALE; + int vios = VIOS_SCALE; + + if (rq_data_dir(rq) == WRITE) + vios = vios * fiopsd->write_scale / fiopsd->read_scale; + + return vios; } /* return vios dispatched */ @@ -500,6 +511,9 @@ static void *fiops_init_queue(struct req INIT_WORK(&fiopsd->unplug_work, fiops_kick_queue); + fiopsd->read_scale = VIOS_READ_SCALE; + fiopsd->write_scale = VIOS_WRITE_SCALE; + return fiopsd; } @@ -517,6 +531,60 @@ static void fiops_init_icq(struct io_cq ioc->pid = current->pid; } +/* + * sysfs parts below --> + */ +static ssize_t +fiops_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +fiops_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + return fiops_var_show(__VAR, (page)); \ +} +SHOW_FUNCTION(fiops_read_scale_show, fiopsd->read_scale); +SHOW_FUNCTION(fiops_write_scale_show, fiopsd->write_scale); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + unsigned int __data; \ + int ret = fiops_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(fiops_read_scale_store, &fiopsd->read_scale, 1, 100); +STORE_FUNCTION(fiops_write_scale_store, &fiopsd->write_scale, 1, 100); +#undef STORE_FUNCTION + +#define FIOPS_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, fiops_##name##_show, fiops_##name##_store) + +static struct elv_fs_entry fiops_attrs[] = { + FIOPS_ATTR(read_scale), + FIOPS_ATTR(write_scale), + __ATTR_NULL +}; + static struct elevator_type iosched_fiops = { .ops = { .elevator_merge_fn = fiops_merge, @@ -534,6 +602,7 @@ static struct elevator_type iosched_fiop }, .icq_size = sizeof(struct fiops_ioc), .icq_align = __alignof__(struct fiops_ioc), + .elevator_attrs = fiops_attrs, .elevator_name = "fiops", .elevator_owner = THIS_MODULE, }; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/