lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 30 Dec 2016 23:57:37 +0100
From:   Thomas Schoebel-Theuer <tst@...oebel-theuer.de>
To:     linux-kernel@...r.kernel.org, tst@...oebel-theuer.de
Subject: [RFC 11/32] mars: add new module lib_timing

Signed-off-by: Thomas Schoebel-Theuer <tst@...oebel-theuer.de>
---
 drivers/staging/mars/lib/lib_timing.c |  68 +++++++++++++
 include/linux/brick/lib_timing.h      | 182 ++++++++++++++++++++++++++++++++++
 2 files changed, 250 insertions(+)
 create mode 100644 drivers/staging/mars/lib/lib_timing.c
 create mode 100644 include/linux/brick/lib_timing.h

diff --git a/drivers/staging/mars/lib/lib_timing.c b/drivers/staging/mars/lib/lib_timing.c
new file mode 100644
index 000000000000..1996052cb647
--- /dev/null
+++ b/drivers/staging/mars/lib/lib_timing.c
@@ -0,0 +1,68 @@
+/*
+ * MARS Long Distance Replication Software
+ *
+ * Copyright (C) 2010-2014 Thomas Schoebel-Theuer
+ * Copyright (C) 2011-2014 1&1 Internet AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/brick/lib_timing.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#ifdef CONFIG_DEBUG_KERNEL
+
+int report_timing(struct timing_stats *tim, char *str, int maxlen)
+{
+	int len = 0;
+	int time = 1;
+	int resol = 1;
+
+	static const char * const units[] = {
+		"us",
+		"ms",
+		"s",
+		"ERROR"
+	};
+	const char *unit = units[0];
+	int unit_index = 0;
+	int i;
+
+	for (i = 0; i < TIMING_MAX; i++) {
+		int this_len = scnprintf(
+
+		str, maxlen, "<%d%s = %d (%lld) ", resol, unit, tim->tim_count[i], (
+		long long)tim->tim_count[i] * time);
+
+		str += this_len;
+		len += this_len;
+		maxlen -= this_len;
+		if (maxlen <= 1)
+			break;
+		resol <<= 1;
+		time <<= 1;
+		if (resol >= 1000) {
+			resol = 1;
+			unit = units[++unit_index];
+		}
+	}
+	return len;
+}
+
+#endif /*  CONFIG_DEBUG_KERNEL */
+
+struct threshold global_io_threshold = {
+	.thr_limit = 30 * 1000000, /*  30 seconds */
+	.thr_factor = 100,
+	.thr_plus = 0,
+};
diff --git a/include/linux/brick/lib_timing.h b/include/linux/brick/lib_timing.h
new file mode 100644
index 000000000000..7081d984a2ce
--- /dev/null
+++ b/include/linux/brick/lib_timing.h
@@ -0,0 +1,182 @@
+/*
+ * MARS Long Distance Replication Software
+ *
+ * Copyright (C) 2010-2014 Thomas Schoebel-Theuer
+ * Copyright (C) 2011-2014 1&1 Internet AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef LIB_TIMING_H
+#define LIB_TIMING_H
+
+#include <linux/sched.h>
+
+/* Simple infrastructure for timing of arbitrary operations and creation
+ * of some simple histogram statistics.
+ */
+
+#define TIMING_MAX			24
+
+struct timing_stats {
+#ifdef CONFIG_DEBUG_KERNEL
+	int tim_count[TIMING_MAX];
+
+#endif
+};
+
+#define _TIME_THIS(_stamp1, _stamp2, _CODE)				\
+	({								\
+		(_stamp1) = cpu_clock(raw_smp_processor_id());		\
+									\
+		_CODE;							\
+									\
+		(_stamp2) = cpu_clock(raw_smp_processor_id());		\
+		(_stamp2) - (_stamp1);					\
+	})
+
+#define TIME_THIS(_CODE)						\
+	({								\
+		unsigned long long _stamp1;				\
+		unsigned long long _stamp2;				\
+		_TIME_THIS(_stamp1, _stamp2, _CODE);			\
+	})
+
+#ifdef CONFIG_DEBUG_KERNEL
+
+#define _TIME_STATS(_timing, _stamp1, _stamp2, _CODE)			\
+	({								\
+		unsigned long long _time;				\
+		unsigned long _tmp;					\
+		int _i;							\
+									\
+		_time = _TIME_THIS(_stamp1, _stamp2, _CODE);		\
+									\
+		_tmp = _time / 1000;	/* convert to us */		\
+		_i = 0;							\
+		while (_tmp > 0 && _i < TIMING_MAX - 1) {		\
+			_tmp >>= 1;					\
+			_i++;						\
+		}							\
+		(_timing)->tim_count[_i]++;				\
+		_time;							\
+	})
+
+#define TIME_STATS(_timing, _CODE)					\
+	({								\
+		unsigned long long _stamp1;				\
+		unsigned long long _stamp2;				\
+		_TIME_STATS(_timing, _stamp1, _stamp2, _CODE);		\
+	})
+
+extern int report_timing(struct timing_stats *tim, char *str, int maxlen);
+
+#else  /*  CONFIG_DEBUG_KERNEL */
+
+#define _TIME_STATS(_timing, _stamp1, _stamp2, _CODE)			\
+	((void)_timing, (_stamp1) = (_stamp2) = cpu_clock(raw_smp_processor_id()), _CODE, 0)
+
+#define TIME_STATS(_timing, _CODE)					\
+	((void)_timing, _CODE, 0)
+
+#define report_timing(tim, str, maxlen)   ((void)tim, 0)
+
+#endif /*  CONFIG_DEBUG_KERNEL */
+
+/* A banning represents some overloaded resource.
+ *
+ * Whenever overload is detected, you should call banning_hit()
+ * telling that the overload is assumed / estimated to continue
+ * for some duration in time.
+ *
+ * ATTENTION! These operations are deliberately raceful.
+ * They are meant to deliver _hints_ (e.g. for IO scheduling
+ * decisions etc), not hard facts!
+ *
+ * If you need locking, just surround these operations
+ * with locking by yourself.
+ */
+struct banning {
+	long long ban_last_hit;
+
+	/*  statistical */
+	int ban_renew_count;
+	int ban_count;
+};
+
+static inline
+bool banning_hit(struct banning *ban, long long duration)
+{
+	long long now = cpu_clock(raw_smp_processor_id());
+	bool hit = ban->ban_last_hit >= now;
+	long long new_hit = now + duration;
+
+	ban->ban_renew_count++;
+	if (!ban->ban_last_hit || ban->ban_last_hit < new_hit) {
+		ban->ban_last_hit = new_hit;
+		ban->ban_count++;
+	}
+	return hit;
+}
+
+static inline
+bool banning_is_hit(struct banning *ban)
+{
+	long long now = cpu_clock(raw_smp_processor_id());
+
+	return (ban->ban_last_hit && ban->ban_last_hit >= now);
+}
+
+extern inline
+void banning_reset(struct banning *ban)
+{
+	ban->ban_last_hit = 0;
+}
+
+/* Threshold: trigger a banning whenever some latency threshold
+ * is exceeded.
+ */
+struct threshold {
+	struct banning *thr_ban;
+
+	struct threshold *thr_parent; /* support hierarchies */
+	/*  tunables */
+	int  thr_limit;   /*  in us */
+	int  thr_factor;  /*  in % */
+	int  thr_plus;	  /*  in us */
+	/*  statistical */
+	int thr_max;	  /*  in ms */
+	int thr_triggered;
+	int thr_true_hit;
+};
+
+static inline
+void threshold_check(struct threshold *thr, long long latency)
+{
+	int ms = latency >> 6; /*  ignore small rounding error */
+
+	while (thr) {
+		if (ms > thr->thr_max)
+			thr->thr_max = ms;
+		if (thr->thr_limit &&
+		    latency > (long long)thr->thr_limit * 1000) {
+			thr->thr_triggered++;
+			if (thr->thr_ban &&
+			    !banning_hit(thr->thr_ban, latency * thr->thr_factor / 100 + thr->thr_plus * 1000))
+				thr->thr_true_hit++;
+		}
+		thr = thr->thr_parent;
+	}
+}
+
+extern struct threshold global_io_threshold;
+
+#endif
-- 
2.11.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ