Merge "block:row: fix idling mechanism in ROW"
diff --git a/block/row-iosched.c b/block/row-iosched.c
index b7965c6..483d97f 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -69,20 +69,19 @@
1 /* ROWQ_PRIO_LOW_SWRITE */
};
-/* Default values for idling on read queues */
-#define ROW_IDLE_TIME 50 /* 5 msec */
-#define ROW_READ_FREQ 70 /* 7 msec */
+/* Default values for idling on read queues (in msec) */
+#define ROW_IDLE_TIME_MSEC 5
+#define ROW_READ_FREQ_MSEC 20
/**
* struct rowq_idling_data - parameters for idling on the queue
- * @idle_trigger_time: time (in jiffies). If a new request was
- * inserted before this time value, idling
- * will be enabled.
+ * @last_insert_time: time the last request was inserted
+ * to the queue
* @begin_idling: flag indicating wether we should idle
*
*/
struct rowq_idling_data {
- unsigned long idle_trigger_time;
+ ktime_t last_insert_time;
bool begin_idling;
};
@@ -111,7 +110,7 @@
/**
* struct idling_data - data for idling on empty rqueue
- * @idle_time: idling duration (msec)
+ * @idle_time: idling duration (jiffies)
* @freq: min time between two requests that
* triger idling (msec)
* @idle_work: pointer to struct delayed_work
@@ -119,7 +118,7 @@
*/
struct idling_data {
unsigned long idle_time;
- unsigned long freq;
+ u32 freq;
struct workqueue_struct *idle_workqueue;
struct delayed_work idle_work;
@@ -260,14 +259,17 @@
if (delayed_work_pending(&rd->read_idle.idle_work))
(void)cancel_delayed_work(
&rd->read_idle.idle_work);
- if (time_before(jiffies, rqueue->idle_data.idle_trigger_time)) {
+ if (ktime_to_ms(ktime_sub(ktime_get(),
+ rqueue->idle_data.last_insert_time)) <
+ rd->read_idle.freq) {
rqueue->idle_data.begin_idling = true;
row_log_rowq(rd, rqueue->prio, "Enable idling");
- } else
+ } else {
rqueue->idle_data.begin_idling = false;
+ row_log_rowq(rd, rqueue->prio, "Disable idling");
+ }
- rqueue->idle_data.idle_trigger_time =
- jiffies + msecs_to_jiffies(rd->read_idle.freq);
+ rqueue->idle_data.last_insert_time = ktime_get();
}
row_log_rowq(rd, rqueue->prio, "added request");
}
@@ -402,9 +404,8 @@
if (!force && queue_idling_enabled[currq] &&
rd->row_queues[currq].rqueue.idle_data.begin_idling) {
if (!queue_delayed_work(rd->read_idle.idle_workqueue,
- &rd->read_idle.idle_work,
- jiffies +
- msecs_to_jiffies(rd->read_idle.idle_time))) {
+ &rd->read_idle.idle_work,
+ rd->read_idle.idle_time)) {
row_log_rowq(rd, currq,
"Work already on queue!");
pr_err("ROW_BUG: Work already on queue!");
@@ -453,6 +454,8 @@
rdata->row_queues[i].rqueue.rdata = rdata;
rdata->row_queues[i].rqueue.prio = i;
rdata->row_queues[i].rqueue.idle_data.begin_idling = false;
+ rdata->row_queues[i].rqueue.idle_data.last_insert_time =
+ ktime_set(0, 0);
}
/*
@@ -460,8 +463,11 @@
* enable it for write queues also, note that idling frequency will
* be the same in both cases
*/
- rdata->read_idle.idle_time = ROW_IDLE_TIME;
- rdata->read_idle.freq = ROW_READ_FREQ;
+ rdata->read_idle.idle_time = msecs_to_jiffies(ROW_IDLE_TIME_MSEC);
+ /* Maybe 0 on some platforms */
+ if (!rdata->read_idle.idle_time)
+ rdata->read_idle.idle_time = 1;
+ rdata->read_idle.freq = ROW_READ_FREQ_MSEC;
rdata->read_idle.idle_workqueue = alloc_workqueue("row_idle_work",
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
if (!rdata->read_idle.idle_workqueue)
@@ -489,6 +495,8 @@
for (i = 0; i < ROWQ_MAX_PRIO; i++)
BUG_ON(!list_empty(&rd->row_queues[i].rqueue.fifo));
(void)cancel_delayed_work_sync(&rd->read_idle.idle_work);
+ BUG_ON(delayed_work_pending(&rd->read_idle.idle_work));
+ destroy_workqueue(rd->read_idle.idle_workqueue);
kfree(rd);
}
@@ -590,7 +598,7 @@
SHOW_FUNCTION(row_lp_swrite_quantum_show,
rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
SHOW_FUNCTION(row_read_idle_show, rowd->read_idle.idle_time, 1);
-SHOW_FUNCTION(row_read_idle_freq_show, rowd->read_idle.freq, 1);
+SHOW_FUNCTION(row_read_idle_freq_show, rowd->read_idle.freq, 0);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -630,7 +638,7 @@
&rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
1, INT_MAX, 1);
STORE_FUNCTION(row_read_idle_store, &rowd->read_idle.idle_time, 1, INT_MAX, 1);
-STORE_FUNCTION(row_read_idle_freq_store, &rowd->read_idle.freq, 1, INT_MAX, 1);
+STORE_FUNCTION(row_read_idle_freq_store, &rowd->read_idle.freq, 1, INT_MAX, 0);
#undef STORE_FUNCTION