summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo2019-05-13 21:37:17 +0200
committerTejun Heo2019-05-31 20:48:40 +0200
commita5e112e6424adb77d953eac20e6936b952fd6b32 (patch)
treef338dc9c274907e5d2321f9e7e4a8608fdb202ea
parentcgroup: Include dying leaders with live threads in PROCS iterations (diff)
downloadkernel-qcow2-linux-a5e112e6424adb77d953eac20e6936b952fd6b32.tar.gz
kernel-qcow2-linux-a5e112e6424adb77d953eac20e6936b952fd6b32.tar.xz
kernel-qcow2-linux-a5e112e6424adb77d953eac20e6936b952fd6b32.zip
cgroup: add cgroup_parse_float()
cgroup already uses floating point for percent[ile] numbers and there are several controllers which want to take them as input. Add a generic parse helper to handle inputs. Update the interface convention documentation about the use of percentage numbers. While at it, also clarify the default time unit. Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--Documentation/admin-guide/cgroup-v2.rst6
-rw-r--r--include/linux/cgroup.h2
-rw-r--r--kernel/cgroup/cgroup.c43
3 files changed, 51 insertions, 0 deletions
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 88e746074252..73b0c0d8df31 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -696,6 +696,12 @@ Conventions
informational files on the root cgroup which end up showing global
information available elsewhere shouldn't exist.
+- The default time unit is microseconds. If a different unit is ever
+ used, an explicit unit suffix must be present.
+
+- A parts-per quantity should use a percentage decimal with at least
+ two digit fractional part - e.g. 13.40.
+
- If a controller implements weight based resource distribution, its
interface file should be named "weight" and have the range [1,
10000] with 100 as the default. The values are chosen to allow
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 0297f930a56e..3745ecdad925 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -131,6 +131,8 @@ void cgroup_free(struct task_struct *p);
int cgroup_init_early(void);
int cgroup_init(void);
+int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v);
+
/*
* Iteration helpers and macros.
*/
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index a7df319c2e9a..7dffcfe17441 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -6387,4 +6387,47 @@ static int __init cgroup_sysfs_init(void)
return sysfs_create_group(kernel_kobj, &cgroup_sysfs_attr_group);
}
subsys_initcall(cgroup_sysfs_init);
+
+static u64 power_of_ten(int power)
+{
+ u64 v = 1;
+ while (power--)
+ v *= 10;
+ return v;
+}
+
+/**
+ * cgroup_parse_float - parse a floating number
+ * @input: input string
+ * @dec_shift: number of decimal digits to shift
+ * @v: output
+ *
+ * Parse a decimal floating point number in @input and store the result in
+ * @v with decimal point right shifted @dec_shift times. For example, if
+ * @input is "12.3456" and @dec_shift is 3, *@v will be set to 12345.
+ * Returns 0 on success, -errno otherwise.
+ *
+ * There's nothing cgroup specific about this function except that it's
+ * currently the only user.
+ */
+int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v)
+{
+ s64 whole, frac = 0;
+ int fstart = 0, fend = 0, flen;
+
+ if (!sscanf(input, "%lld.%n%lld%n", &whole, &fstart, &frac, &fend))
+ return -EINVAL;
+ if (frac < 0)
+ return -EINVAL;
+
+ flen = fend > fstart ? fend - fstart : 0;
+ if (flen < dec_shift)
+ frac *= power_of_ten(dec_shift - flen);
+ else
+ frac = DIV_ROUND_CLOSEST_ULL(frac, power_of_ten(flen - dec_shift));
+
+ *v = whole * power_of_ten(dec_shift) + frac;
+ return 0;
+}
+
#endif /* CONFIG_SYSFS */