[patch v2 2/8]block: fiops read/write request scale

From: Shaohua Li
Date: Mon Jan 30 2012 - 02:07:34 EST


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 <shaohua.li@xxxxxxxxx>
---
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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/