|
@@ -489,3 +489,73 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
|
|
|
throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);
|
|
|
|
|
|
time_elapsed = jiffies - tg->slice_start[rw];
|
|
|
+
|
|
|
+ nr_slices = time_elapsed / throtl_slice;
|
|
|
+
|
|
|
+ if (!nr_slices)
|
|
|
+ return;
|
|
|
+ tmp = tg->bps[rw] * throtl_slice * nr_slices;
|
|
|
+ do_div(tmp, HZ);
|
|
|
+ bytes_trim = tmp;
|
|
|
+
|
|
|
+ io_trim = (tg->iops[rw] * throtl_slice * nr_slices)/HZ;
|
|
|
+
|
|
|
+ if (!bytes_trim && !io_trim)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (tg->bytes_disp[rw] >= bytes_trim)
|
|
|
+ tg->bytes_disp[rw] -= bytes_trim;
|
|
|
+ else
|
|
|
+ tg->bytes_disp[rw] = 0;
|
|
|
+
|
|
|
+ if (tg->io_disp[rw] >= io_trim)
|
|
|
+ tg->io_disp[rw] -= io_trim;
|
|
|
+ else
|
|
|
+ tg->io_disp[rw] = 0;
|
|
|
+
|
|
|
+ tg->slice_start[rw] += nr_slices * throtl_slice;
|
|
|
+
|
|
|
+ throtl_log_tg(td, tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu"
|
|
|
+ " start=%lu end=%lu jiffies=%lu",
|
|
|
+ rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim,
|
|
|
+ tg->slice_start[rw], tg->slice_end[rw], jiffies);
|
|
|
+}
|
|
|
+
|
|
|
+static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,
|
|
|
+ struct bio *bio, unsigned long *wait)
|
|
|
+{
|
|
|
+ bool rw = bio_data_dir(bio);
|
|
|
+ unsigned int io_allowed;
|
|
|
+ unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
|
|
|
+ u64 tmp;
|
|
|
+
|
|
|
+ jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
|
|
|
+
|
|
|
+ /* Slice has just started. Consider one slice interval */
|
|
|
+ if (!jiffy_elapsed)
|
|
|
+ jiffy_elapsed_rnd = throtl_slice;
|
|
|
+
|
|
|
+ jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * jiffy_elapsed_rnd should not be a big value as minimum iops can be
|
|
|
+ * 1 then at max jiffy elapsed should be equivalent of 1 second as we
|
|
|
+ * will allow dispatch after 1 second and after that slice should
|
|
|
+ * have been trimmed.
|
|
|
+ */
|
|
|
+
|
|
|
+ tmp = (u64)tg->iops[rw] * jiffy_elapsed_rnd;
|
|
|
+ do_div(tmp, HZ);
|
|
|
+
|
|
|
+ if (tmp > UINT_MAX)
|
|
|
+ io_allowed = UINT_MAX;
|
|
|
+ else
|
|
|
+ io_allowed = tmp;
|
|
|
+
|
|
|
+ if (tg->io_disp[rw] + 1 <= io_allowed) {
|
|
|
+ if (wait)
|
|
|
+ *wait = 0;
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Calc approx time to dispatch */
|