From 628c636dff8c73008632fc5d1f766154ed1c82c7 Mon Sep 17 00:00:00 2001 From: Thomas Schoebel-Theuer Date: Tue, 19 Jan 2016 09:15:44 +0100 Subject: [PATCH] all: distinguish *_ops_* from *_amount_* at limiter --- kernel/lib_limiter.c | 72 ++++++++++++++++++++++++++++----------- kernel/lib_limiter.h | 15 ++++---- kernel/mars_client.c | 2 +- kernel/mars_if.c | 2 +- kernel/mars_server.c | 2 +- kernel/sy_old/mars_main.c | 19 ++++++++--- kernel/sy_old/mars_proc.c | 14 ++++---- userspace/marsadm | 30 +++++++++++----- 8 files changed, 109 insertions(+), 47 deletions(-) diff --git a/kernel/lib_limiter.c b/kernel/lib_limiter.c index b693d627..fe9b627c 100644 --- a/kernel/lib_limiter.c +++ b/kernel/lib_limiter.c @@ -61,8 +61,10 @@ int mars_limit(struct mars_limiter *lim, int amount) * They will intentionally wrap around. * Userspace must take care of that. */ - lim->lim_total_ops++; - lim->lim_total_sum += amount; + if (likely(amount > 0)) { + lim->lim_total_amount += amount; + lim->lim_total_ops++; + } /* Only use incremental accumulation at repeated calls, but * never after longer pauses. @@ -71,26 +73,48 @@ int mars_limit(struct mars_limiter *lim, int amount) window < (long long)lim->lim_max_window * (LIMITER_TIME_RESOLUTION / 1000))) { long long rate_raw; int rate; + int max_rate; /* Races are possible, but taken into account. * There is no real harm from rarely lost updates. */ if (likely(amount > 0)) { - lim->lim_accu += amount; - lim->lim_cumul += amount; - lim->lim_count++; + lim->lim_amount_accu += amount; + lim->lim_amount_cumul += amount; + lim->lim_ops_accu++; + lim->lim_ops_cumul++; } - - rate_raw = lim->lim_accu * LIMITER_TIME_RESOLUTION / window; + + /* compute amount values */ + rate_raw = lim->lim_amount_accu * LIMITER_TIME_RESOLUTION / window; rate = rate_raw; if (unlikely(rate_raw > INT_MAX)) { rate = INT_MAX; } - lim->lim_rate = rate; + lim->lim_amount_rate = rate; - // limit exceeded? - if (lim->lim_max_rate > 0 && rate > lim->lim_max_rate) { - int this_delay = (window * rate / lim->lim_max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000); + /* amount limit exceeded? */ + max_rate = lim->lim_max_amount_rate; + if (max_rate > 0 && rate > max_rate) { + int this_delay = (window * rate / max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000); + // compute maximum + if (this_delay > delay && this_delay > 0) + delay = this_delay; + } + + /* compute ops values */ + rate_raw = lim->lim_ops_accu * LIMITER_TIME_RESOLUTION / window; + rate = rate_raw; + if (unlikely(rate_raw > INT_MAX)) { + rate = INT_MAX; + } + lim->lim_ops_rate = rate; + + /* ops limit exceeded? */ + max_rate = lim->lim_max_ops_rate; + if (max_rate > 0 && rate > max_rate) { + int this_delay = (window * rate / max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000); + // compute maximum if (this_delay > delay && this_delay > 0) delay = this_delay; @@ -100,30 +124,41 @@ int mars_limit(struct mars_limiter *lim, int amount) */ window -= lim->lim_min_window * (LIMITER_TIME_RESOLUTION / 1000); if (window > 0) { - long long used_up = (long long)lim->lim_rate * window / LIMITER_TIME_RESOLUTION; + long long used_up = (long long)lim->lim_amount_rate * window / LIMITER_TIME_RESOLUTION; if (used_up > 0) { lamport_time_add_ns(&lim->lim_stamp, window); - lim->lim_accu -= used_up; - if (unlikely(lim->lim_accu < 0)) - lim->lim_accu = 0; + lim->lim_amount_accu -= used_up; + if (unlikely(lim->lim_amount_accu < 0)) + lim->lim_amount_accu = 0; + } + used_up = (long long)lim->lim_ops_rate * window / LIMITER_TIME_RESOLUTION; + if (used_up > 0) { + lamport_time_add_ns(&lim->lim_stamp, window); + lim->lim_ops_accu -= used_up; + if (unlikely(lim->lim_ops_accu < 0)) + lim->lim_ops_accu = 0; } } } else { // reset, start over with new measurement cycle struct lamport_time sub = ns_to_lamport_time(lim->lim_min_window * (LIMITER_TIME_RESOLUTION / 1000)); + if (unlikely(amount < 0)) + amount = 0; + lim->lim_ops_accu = 1; + lim->lim_amount_accu = amount; lim->lim_stamp = lamport_time_sub(now, sub); - lim->lim_accu = amount; - lim->lim_rate = 0; + lim->lim_ops_rate = 0; + lim->lim_amount_rate = 0; } lim = lim->lim_father; } return delay; } -EXPORT_SYMBOL_GPL(mars_limit); void mars_limit_sleep(struct mars_limiter *lim, int amount) { int sleep = mars_limit(lim, amount); + if (sleep > 0) { if (unlikely(lim->lim_max_delay <= 0)) lim->lim_max_delay = 1000; @@ -132,7 +167,6 @@ void mars_limit_sleep(struct mars_limiter *lim, int amount) brick_msleep(sleep); } } -EXPORT_SYMBOL_GPL(mars_limit_sleep); void mars_limit_reset(struct mars_limiter *lim) { diff --git a/kernel/lib_limiter.h b/kernel/lib_limiter.h index c3a017cb..960c3837 100644 --- a/kernel/lib_limiter.h +++ b/kernel/lib_limiter.h @@ -33,19 +33,22 @@ struct mars_limiter { /* hierarchy tree */ struct mars_limiter *lim_father; /* tunables */ - int lim_max_rate; + int lim_max_ops_rate; + int lim_max_amount_rate; int lim_max_delay; int lim_min_window; int lim_max_window; /* readable */ - int lim_rate; - int lim_cumul; - int lim_count; + int lim_ops_rate; + int lim_amount_rate; + int lim_ops_cumul; + int lim_amount_cumul; int lim_total_ops; - int lim_total_sum; + int lim_total_amount; struct lamport_time lim_stamp; /* internal */ - long long lim_accu; + long long lim_ops_accu; + long long lim_amount_accu; }; extern int mars_limit(struct mars_limiter *lim, int amount); diff --git a/kernel/mars_client.c b/kernel/mars_client.c index 5a016b95..5578a4ed 100644 --- a/kernel/mars_client.c +++ b/kernel/mars_client.c @@ -1161,7 +1161,7 @@ EXPORT_SYMBOL_GPL(client_brick_type); ////////////////// module init stuff ///////////////////////// struct mars_limiter client_limiter = { - .lim_max_rate = 0, + /* Let all be zero */ }; EXPORT_SYMBOL_GPL(client_limiter); diff --git a/kernel/mars_if.c b/kernel/mars_if.c index c8de5cd4..e3b7ba15 100644 --- a/kernel/mars_if.c +++ b/kernel/mars_if.c @@ -78,7 +78,7 @@ int if_throttle_start_size = 0; // in kb EXPORT_SYMBOL_GPL(if_throttle_start_size); struct mars_limiter if_throttle = { - .lim_max_rate = 10000, + .lim_max_amount_rate = 10000, }; ///////////////////////// own type definitions //////////////////////// diff --git a/kernel/mars_server.c b/kernel/mars_server.c index 50ad9f32..99e7919f 100644 --- a/kernel/mars_server.c +++ b/kernel/mars_server.c @@ -936,7 +936,7 @@ static int _server_thread(void *data) ////////////////// module init stuff ///////////////////////// struct mars_limiter server_limiter = { - .lim_max_rate = 0, + /* Let all be zero */ }; EXPORT_SYMBOL_GPL(server_limiter); diff --git a/kernel/sy_old/mars_main.c b/kernel/sy_old/mars_main.c index 05fbeeed..79a7c667 100644 --- a/kernel/sy_old/mars_main.c +++ b/kernel/sy_old/mars_main.c @@ -1606,10 +1606,19 @@ void _show_status_all(struct mars_global *global) } static -void _show_rate(struct mars_rotate *rot, struct mars_limiter *limiter, const char *name) +void _show_rate(struct mars_rotate *rot, struct mars_limiter *limiter, const char *basename) { + char *name; + mars_limit(limiter, 0); - __show_actual(rot->parent_path, name, limiter->lim_rate); + + name = path_make("ops-%s", basename); + __show_actual(rot->parent_path, name, limiter->lim_ops_rate); + brick_string_free(name); + + name = path_make("amount-%s", basename); + __show_actual(rot->parent_path, name, limiter->lim_amount_rate); + brick_string_free(name); } /////////////////////////////////////////////////////////////////////// @@ -1758,7 +1767,8 @@ int __make_copy( "from = '%s' to = '%s'" " on = %d start_pos = %lld end_pos = %lld" " actual_pos = %lld actual_stamp = %ld.%09ld" - " rate = %d read_fly = %d write_fly = %d error_code = %d nr_errors = %d", + " ops_rate = %d amount_rate = %d" + " read_fly = %d write_fly = %d error_code = %d nr_errors = %d", argv[0], argv[1], _copy->power.led_on, @@ -1766,7 +1776,8 @@ int __make_copy( _copy->copy_end, _copy->copy_last, _copy->copy_last_stamp.tv_sec, _copy->copy_last_stamp.tv_nsec, - _copy->copy_limiter ? _copy->copy_limiter->lim_rate : 0, + _copy->copy_limiter ? _copy->copy_limiter->lim_ops_rate : 0, + _copy->copy_limiter ? _copy->copy_limiter->lim_amount_rate : 0, atomic_read(&_copy->copy_read_flight), atomic_read(&_copy->copy_write_flight), _copy->copy_error, diff --git a/kernel/sy_old/mars_proc.c b/kernel/sy_old/mars_proc.c index 741223ce..205f357b 100644 --- a/kernel/sy_old/mars_proc.c +++ b/kernel/sy_old/mars_proc.c @@ -240,15 +240,17 @@ done: VEC_ENTRY(NAME, VAR, MODE, 1) #define LIMITER_ENTRIES(VAR, PREFIX, SUFFIX) \ - INT_ENTRY(PREFIX "_total_ops_" SUFFIX, (VAR)->lim_total_ops, 0400), \ - INT_ENTRY(PREFIX "_total_sum_" SUFFIX, (VAR)->lim_total_sum, 0400), \ - INT_ENTRY(PREFIX "_ratelimit_" SUFFIX, (VAR)->lim_max_rate, 0600), \ + INT_ENTRY(PREFIX "_total_ops", (VAR)->lim_total_ops, 0400), \ + INT_ENTRY(PREFIX "_total_" SUFFIX, (VAR)->lim_total_amount, 0400), \ + INT_ENTRY(PREFIX "_ratelimit_ops", (VAR)->lim_max_ops_rate, 0600), \ + INT_ENTRY(PREFIX "_ratelimit_" SUFFIX, (VAR)->lim_max_amount_rate, 0600), \ INT_ENTRY(PREFIX "_maxdelay_ms", (VAR)->lim_max_delay,0600), \ INT_ENTRY(PREFIX "_minwindow_ms", (VAR)->lim_min_window,0600), \ INT_ENTRY(PREFIX "_maxwindow_ms", (VAR)->lim_max_window,0600), \ - INT_ENTRY(PREFIX "_cumul_" SUFFIX, (VAR)->lim_cumul, 0600), \ - INT_ENTRY(PREFIX "_count_ops", (VAR)->lim_count, 0600), \ - INT_ENTRY(PREFIX "_rate_" SUFFIX, (VAR)->lim_rate, 0400) \ + INT_ENTRY(PREFIX "_cumul_ops", (VAR)->lim_ops_cumul, 0600), \ + INT_ENTRY(PREFIX "_cumul_" SUFFIX, (VAR)->lim_amount_cumul, 0600), \ + INT_ENTRY(PREFIX "_rate_ops", (VAR)->lim_ops_rate, 0400), \ + INT_ENTRY(PREFIX "_rate_" SUFFIX, (VAR)->lim_amount_rate, 0400) \ #define THRESHOLD_ENTRIES(VAR, PREFIX) \ INT_ENTRY(PREFIX "_threshold_us", (VAR)->thr_limit, 0600), \ diff --git a/userspace/marsadm b/userspace/marsadm index 1551a8b1..0d875f1d 100755 --- a/userspace/marsadm +++ b/userspace/marsadm @@ -5418,7 +5418,7 @@ sub eval_fn { my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/replay-code"; return get_link($lnk, 2); } - if (/^(sync|fetch|replay|work)[-_]?(rate|remain)$/) { + if (/^(sync|fetch|replay|work)[-_]?(rate|ops[-_]?rate|amount[-_]?rate|remain)$/) { my $what = $1; my $select = $2; if ($what eq "work") { @@ -5433,22 +5433,34 @@ sub eval_fn { return $val1 if $val1 > $val2; return $val2; } + my $name = $select; + $name = "amount_rate" if ($name eq "rate" || $name eq "remain"); + $name =~ s/-/_/; my %names = ( - "sync" => "sync_rate", - "fetch" => "file_rate", - "replay" => "replay_rate", + "sync" => "sync", + "fetch" => "file", + "replay" => "replay", ); - my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/" . $names{$what}; + $name =~ s/_/-$names{$what}_/; + my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/$name"; my $rate = get_link($lnk, 2); - return "" if !defined($rate) || $rate eq "" || $rate < 0; - return $rate * 1024 if $select eq "rate"; + # deprecated: compatibility with old version + if (!defined($rate) || $rate eq "") { + $lnk =~ s:/amount-:/:; + $rate = get_link($lnk, 2); + } if ($select eq "remain") { my $rest = make_numeric(eval_fn($env, "$what-rest", "")); return 0 if $rest <= 0; - return -1 if ($rate <= 0); + return -1 if (!defined($rate) || $rate eq "" || $rate <= 0); return $rest / 1024 / $rate; } + if ($select =~ /rate/) { + return 0 if (!defined($rate) || !$rate || $rate <= 0); + return $rate if $select =~ /^ops-/; + return $rate * 1024; + } ldie "unknown macro $_\n"; } if (/^sync[-_]?size$/) { @@ -6431,7 +6443,7 @@ my %trivial_globs = => "", "writeback-rest" => "", - "{sync,fetch,replay}-{rate,remain}" + "{sync,fetch,replay}-{ops-rate,amount-rate,rate,remain}" => "", "replay-basenr" => "",