[RFC 3/3]block: fiops read/write request scale

From: Shaohua Li
Date: Wed Jan 04 2012 - 01:40:37 EST


read/write speed of Flash based storage usually is different. Add a scale
to differenate read and write. Also add a tunable, so user can assign
different scale for read and write. This can also be used to bias read
or write in the system

Signed-off-by: Shaohua Li <shaohua.li@xxxxxxxxx>
---
block/fiops-iosched.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)

Index: linux/block/fiops-iosched.c
===================================================================
--- linux.orig/block/fiops-iosched.c 2012-01-04 14:01:26.000000000 +0800
+++ linux/block/fiops-iosched.c 2012-01-04 14:05:48.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;
@@ -32,6 +35,9 @@ struct fiops_data {
unsigned int busy_queues;

struct work_struct unplug_work;
+
+ unsigned int read_scale;
+ unsigned int write_scale;
};

struct fiops_ioc {
@@ -268,7 +274,10 @@ 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;
+ if (rq_data_dir(rq) == READ)
+ return VIOS_SCALE;
+ else
+ return VIOS_SCALE * fiopsd->write_scale / fiopsd->read_scale;
}

/* return vios dispatched */
@@ -540,6 +549,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;
}

@@ -610,6 +622,60 @@ static struct ioc_builder ioc_builder =
.cic_exit = fiops_exit_cic,
};

+/*
+ * 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,
@@ -626,6 +692,7 @@ static struct elevator_type iosched_fiop
.elevator_exit_fn = fiops_exit_queue,
.trim = queue_data_free_io_context,
},
+ .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/