@@ -3338,10 +3338,21 @@ static void blk_mq_poll_stats_start(struct request_queue *q)
blk_stat_activate_msecs(q->poll_cb, 100);
}
+/*
+ * Thresholds are ilog2(nr_requests / nr_misses)
+ * To calculate tolerated miss ratio from it, use
+ * f(x) ~= 2 ^ -(x + 1)
+ *
+ * fallback ~ 3.1%
+ * throttle ~ 0.4%
+ */
+#define BLK_POLL_FALLBACK_THRESHOLD 4
+#define BLK_POLL_THROTTLE_THRESHOLD 7
+
static void blk_mq_update_poll_info(struct poll_info *pi,
struct blk_rq_stat *stat)
{
- u64 sleep_ns;
+ u64 half_mean, indent, sleep_ns;
u32 nr_misses, nr_samples;
nr_samples = stat->nr_samples;
@@ -3349,14 +3360,33 @@ static void blk_mq_update_poll_info(struct poll_info *pi,
if (nr_misses > nr_samples)
nr_misses = nr_samples;
- if (!nr_samples)
+ half_mean = (stat->mean + 1) / 2;
+ indent = stat->lmd * 4;
+
+ if (!stat->nr_samples) {
sleep_ns = 0;
- else
- sleep_ns = (stat->mean + 1) / 2;
+ } else if (!stat->lmd || stat->mean <= indent) {
+ sleep_ns = half_mean;
+ } else {
+ int ratio = INT_MAX;
- /*
- * Use miss ratio here to adjust sleep time
- */
+ sleep_ns = stat->mean - indent;
+
+ /*
+ * If a completion is overslept, the observable time will
+ * be greater than the actual, so increasing mean. It
+ * also increases sleep time estimation, synergistically
+ * backfiring on mean. Need to scale down / fallback early.
+ */
+ if (nr_misses)
+ ratio = ilog2(nr_samples / nr_misses);
+ if (ratio <= BLK_POLL_FALLBACK_THRESHOLD)
+ sleep_ns = half_mean;
+ else if (ratio <= BLK_POLL_THROTTLE_THRESHOLD)
+ sleep_ns -= sleep_ns / 4;
+
+ sleep_ns = max(sleep_ns, half_mean);
+ }
pi->stat = *stat;
pi->sleep_ns = sleep_ns;