Commit a5e112e6 authored by Tejun Heo's avatar Tejun Heo

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: default avatarTejun Heo <tj@kernel.org>
parent c03cd773
...@@ -696,6 +696,12 @@ Conventions ...@@ -696,6 +696,12 @@ Conventions
informational files on the root cgroup which end up showing global informational files on the root cgroup which end up showing global
information available elsewhere shouldn't exist. 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 - If a controller implements weight based resource distribution, its
interface file should be named "weight" and have the range [1, interface file should be named "weight" and have the range [1,
10000] with 100 as the default. The values are chosen to allow 10000] with 100 as the default. The values are chosen to allow
......
...@@ -131,6 +131,8 @@ void cgroup_free(struct task_struct *p); ...@@ -131,6 +131,8 @@ void cgroup_free(struct task_struct *p);
int cgroup_init_early(void); int cgroup_init_early(void);
int cgroup_init(void); int cgroup_init(void);
int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v);
/* /*
* Iteration helpers and macros. * Iteration helpers and macros.
*/ */
......
...@@ -6387,4 +6387,47 @@ static int __init cgroup_sysfs_init(void) ...@@ -6387,4 +6387,47 @@ static int __init cgroup_sysfs_init(void)
return sysfs_create_group(kernel_kobj, &cgroup_sysfs_attr_group); return sysfs_create_group(kernel_kobj, &cgroup_sysfs_attr_group);
} }
subsys_initcall(cgroup_sysfs_init); 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 */ #endif /* CONFIG_SYSFS */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment