[lustre-devel] [PATCH 5/6] Throttle the outgoing requests according to tau

Yan Li yanli at ascar.io
Tue Mar 21 12:43:32 PDT 2017


Signed-off-by: Yan Li <yanli at ascar.io>
---
 lustre/osc/osc_cache.c    |  3 +++
 lustre/osc/osc_internal.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c
index 236263c..2f9d4e1 100644
--- a/lustre/osc/osc_cache.c
+++ b/lustre/osc/osc_cache.c
@@ -2316,6 +2316,9 @@ static int osc_io_unplug0(const struct lu_env *env, struct client_obd *cli,
 	} else {
 		CDEBUG(D_CACHE, "Queue writeback work for client %p.\n", cli);
 		LASSERT(cli->cl_writeback_work != NULL);
+#ifdef ENABLE_RLQOS
+		qos_throttle(&cli->qos);
+#endif
 		rc = ptlrpcd_queue_work(cli->cl_writeback_work);
 	}
 	return rc;
diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h
index 06c21b3..d31d5ba 100644
--- a/lustre/osc/osc_internal.h
+++ b/lustre/osc/osc_internal.h
@@ -245,4 +245,70 @@ extern unsigned long osc_cache_shrink_count(struct shrinker *sk,
 extern unsigned long osc_cache_shrink_scan(struct shrinker *sk,
 					   struct shrink_control *sc);
 
+#ifdef ENABLE_RLQOS
+static inline void qos_throttle(struct qos_data_t *qos)
+{
+	struct timeval now;
+	long           usec_since_last_rpc;
+	long           need_sleep_usec = 0;
+
+	spin_lock(&qos->lock);
+	if (0 == qos->min_usec_between_rpcs)
+		goto out;
+
+	do_gettimeofday(&now);
+	usec_since_last_rpc = cfs_timeval_sub(&now, &qos->last_rpc_time, NULL);
+	if (usec_since_last_rpc < 0) {
+		usec_since_last_rpc = 0;
+	}
+	if (usec_since_last_rpc < qos->min_usec_between_rpcs) {
+		need_sleep_usec = qos->min_usec_between_rpcs - usec_since_last_rpc;
+	}
+	qos->last_rpc_time = now;
+out:
+	spin_unlock(&qos->lock);
+	if (0 == need_sleep_usec) {
+		return;
+	}
+
+	/* About timer ranges:
+	   Ref: https://www.kernel.org/doc/Documentation/timers/timers-howto.txt */
+	if (need_sleep_usec < 1000) {
+		udelay(need_sleep_usec);
+	} else if (need_sleep_usec < 20000) {
+		usleep_range(need_sleep_usec - 1, need_sleep_usec);
+	} else {
+		msleep(need_sleep_usec / 1000);
+	}
+}
+#endif /* ENABLE_RLQOS */
+
+/* You must call LPROCFS_CLIMP_CHECK() on the obd device before and
+ * LPROCFS_CLIMP_EXIT() after calling this function. They are not called inside
+ * this function, because they may return an error code.
+ */
+static inline void set_max_rpcs_in_flight(int val, struct client_obd *cli)
+{
+	int adding, added, req_count;
+
+	adding = val - cli->cl_max_rpcs_in_flight;
+	req_count = atomic_read(&osc_pool_req_count);
+	if (adding > 0 && req_count < osc_reqpool_maxreqcount) {
+		/*
+		 * There might be some race which will cause over-limit
+		 * allocation, but it is fine.
+		 */
+		if (req_count + adding > osc_reqpool_maxreqcount)
+			adding = osc_reqpool_maxreqcount - req_count;
+
+		added = osc_rq_pool->prp_populate(osc_rq_pool, adding);
+		atomic_add(added, &osc_pool_req_count);
+	}
+
+	spin_lock(&cli->cl_loi_list_lock);
+	cli->cl_max_rpcs_in_flight = val;
+	client_adjust_max_dirty(cli);
+	spin_unlock(&cli->cl_loi_list_lock);
+}
+
 #endif /* OSC_INTERNAL_H */
-- 
1.8.3.1



More information about the lustre-devel mailing list