cgroup/misc: Change counters to be explicit 64bit types

So the variables can account for resources of huge quantities even on
32-bit machines.

Signed-off-by: Haitao Huang <haitao.huang@linux.intel.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Haitao Huang 2023-07-17 18:08:45 -07:00 committed by Tejun Heo
parent 62157e11d9
commit 32bf85c60c
2 changed files with 38 additions and 42 deletions

View File

@ -34,9 +34,9 @@ struct misc_cg;
* @events: Number of times, the resource limit exceeded. * @events: Number of times, the resource limit exceeded.
*/ */
struct misc_res { struct misc_res {
unsigned long max; u64 max;
atomic_long_t usage; atomic64_t usage;
atomic_long_t events; atomic64_t events;
}; };
/** /**
@ -54,12 +54,10 @@ struct misc_cg {
struct misc_res res[MISC_CG_RES_TYPES]; struct misc_res res[MISC_CG_RES_TYPES];
}; };
unsigned long misc_cg_res_total_usage(enum misc_res_type type); u64 misc_cg_res_total_usage(enum misc_res_type type);
int misc_cg_set_capacity(enum misc_res_type type, unsigned long capacity); int misc_cg_set_capacity(enum misc_res_type type, u64 capacity);
int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount);
unsigned long amount); void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, u64 amount);
void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg,
unsigned long amount);
/** /**
* css_misc() - Get misc cgroup from the css. * css_misc() - Get misc cgroup from the css.
@ -100,27 +98,26 @@ static inline void put_misc_cg(struct misc_cg *cg)
#else /* !CONFIG_CGROUP_MISC */ #else /* !CONFIG_CGROUP_MISC */
static inline unsigned long misc_cg_res_total_usage(enum misc_res_type type) static inline u64 misc_cg_res_total_usage(enum misc_res_type type)
{ {
return 0; return 0;
} }
static inline int misc_cg_set_capacity(enum misc_res_type type, static inline int misc_cg_set_capacity(enum misc_res_type type, u64 capacity)
unsigned long capacity)
{ {
return 0; return 0;
} }
static inline int misc_cg_try_charge(enum misc_res_type type, static inline int misc_cg_try_charge(enum misc_res_type type,
struct misc_cg *cg, struct misc_cg *cg,
unsigned long amount) u64 amount)
{ {
return 0; return 0;
} }
static inline void misc_cg_uncharge(enum misc_res_type type, static inline void misc_cg_uncharge(enum misc_res_type type,
struct misc_cg *cg, struct misc_cg *cg,
unsigned long amount) u64 amount)
{ {
} }

View File

@ -14,7 +14,7 @@
#include <linux/misc_cgroup.h> #include <linux/misc_cgroup.h>
#define MAX_STR "max" #define MAX_STR "max"
#define MAX_NUM ULONG_MAX #define MAX_NUM U64_MAX
/* Miscellaneous res name, keep it in sync with enum misc_res_type */ /* Miscellaneous res name, keep it in sync with enum misc_res_type */
static const char *const misc_res_name[] = { static const char *const misc_res_name[] = {
@ -37,7 +37,7 @@ static struct misc_cg root_cg;
* more than the actual capacity. We are using Limits resource distribution * more than the actual capacity. We are using Limits resource distribution
* model of cgroup for miscellaneous controller. * model of cgroup for miscellaneous controller.
*/ */
static unsigned long misc_res_capacity[MISC_CG_RES_TYPES]; static u64 misc_res_capacity[MISC_CG_RES_TYPES];
/** /**
* parent_misc() - Get the parent of the passed misc cgroup. * parent_misc() - Get the parent of the passed misc cgroup.
@ -74,10 +74,10 @@ static inline bool valid_type(enum misc_res_type type)
* Context: Any context. * Context: Any context.
* Return: Current total usage of the resource. * Return: Current total usage of the resource.
*/ */
unsigned long misc_cg_res_total_usage(enum misc_res_type type) u64 misc_cg_res_total_usage(enum misc_res_type type)
{ {
if (valid_type(type)) if (valid_type(type))
return atomic_long_read(&root_cg.res[type].usage); return atomic64_read(&root_cg.res[type].usage);
return 0; return 0;
} }
@ -95,7 +95,7 @@ EXPORT_SYMBOL_GPL(misc_cg_res_total_usage);
* * %0 - Successfully registered the capacity. * * %0 - Successfully registered the capacity.
* * %-EINVAL - If @type is invalid. * * %-EINVAL - If @type is invalid.
*/ */
int misc_cg_set_capacity(enum misc_res_type type, unsigned long capacity) int misc_cg_set_capacity(enum misc_res_type type, u64 capacity)
{ {
if (!valid_type(type)) if (!valid_type(type))
return -EINVAL; return -EINVAL;
@ -114,9 +114,9 @@ EXPORT_SYMBOL_GPL(misc_cg_set_capacity);
* Context: Any context. * Context: Any context.
*/ */
static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg, static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg,
unsigned long amount) u64 amount)
{ {
WARN_ONCE(atomic_long_add_negative(-amount, &cg->res[type].usage), WARN_ONCE(atomic64_add_negative(-amount, &cg->res[type].usage),
"misc cgroup resource %s became less than 0", "misc cgroup resource %s became less than 0",
misc_res_name[type]); misc_res_name[type]);
} }
@ -137,13 +137,12 @@ static void misc_cg_cancel_charge(enum misc_res_type type, struct misc_cg *cg,
* * -EBUSY - If max limit will be crossed or total usage will be more than the * * -EBUSY - If max limit will be crossed or total usage will be more than the
* capacity. * capacity.
*/ */
int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg, u64 amount)
unsigned long amount)
{ {
struct misc_cg *i, *j; struct misc_cg *i, *j;
int ret; int ret;
struct misc_res *res; struct misc_res *res;
int new_usage; s64 new_usage;
if (!(valid_type(type) && cg && READ_ONCE(misc_res_capacity[type]))) if (!(valid_type(type) && cg && READ_ONCE(misc_res_capacity[type])))
return -EINVAL; return -EINVAL;
@ -154,7 +153,7 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg,
for (i = cg; i; i = parent_misc(i)) { for (i = cg; i; i = parent_misc(i)) {
res = &i->res[type]; res = &i->res[type];
new_usage = atomic_long_add_return(amount, &res->usage); new_usage = atomic64_add_return(amount, &res->usage);
if (new_usage > READ_ONCE(res->max) || if (new_usage > READ_ONCE(res->max) ||
new_usage > READ_ONCE(misc_res_capacity[type])) { new_usage > READ_ONCE(misc_res_capacity[type])) {
ret = -EBUSY; ret = -EBUSY;
@ -165,7 +164,7 @@ int misc_cg_try_charge(enum misc_res_type type, struct misc_cg *cg,
err_charge: err_charge:
for (j = i; j; j = parent_misc(j)) { for (j = i; j; j = parent_misc(j)) {
atomic_long_inc(&j->res[type].events); atomic64_inc(&j->res[type].events);
cgroup_file_notify(&j->events_file); cgroup_file_notify(&j->events_file);
} }
@ -184,8 +183,7 @@ EXPORT_SYMBOL_GPL(misc_cg_try_charge);
* *
* Context: Any context. * Context: Any context.
*/ */
void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, void misc_cg_uncharge(enum misc_res_type type, struct misc_cg *cg, u64 amount)
unsigned long amount)
{ {
struct misc_cg *i; struct misc_cg *i;
@ -209,7 +207,7 @@ static int misc_cg_max_show(struct seq_file *sf, void *v)
{ {
int i; int i;
struct misc_cg *cg = css_misc(seq_css(sf)); struct misc_cg *cg = css_misc(seq_css(sf));
unsigned long max; u64 max;
for (i = 0; i < MISC_CG_RES_TYPES; i++) { for (i = 0; i < MISC_CG_RES_TYPES; i++) {
if (READ_ONCE(misc_res_capacity[i])) { if (READ_ONCE(misc_res_capacity[i])) {
@ -217,7 +215,7 @@ static int misc_cg_max_show(struct seq_file *sf, void *v)
if (max == MAX_NUM) if (max == MAX_NUM)
seq_printf(sf, "%s max\n", misc_res_name[i]); seq_printf(sf, "%s max\n", misc_res_name[i]);
else else
seq_printf(sf, "%s %lu\n", misc_res_name[i], seq_printf(sf, "%s %llu\n", misc_res_name[i],
max); max);
} }
} }
@ -241,13 +239,13 @@ static int misc_cg_max_show(struct seq_file *sf, void *v)
* Return: * Return:
* * >= 0 - Number of bytes processed in the input. * * >= 0 - Number of bytes processed in the input.
* * -EINVAL - If buf is not valid. * * -EINVAL - If buf is not valid.
* * -ERANGE - If number is bigger than the unsigned long capacity. * * -ERANGE - If number is bigger than the u64 capacity.
*/ */
static ssize_t misc_cg_max_write(struct kernfs_open_file *of, char *buf, static ssize_t misc_cg_max_write(struct kernfs_open_file *of, char *buf,
size_t nbytes, loff_t off) size_t nbytes, loff_t off)
{ {
struct misc_cg *cg; struct misc_cg *cg;
unsigned long max; u64 max;
int ret = 0, i; int ret = 0, i;
enum misc_res_type type = MISC_CG_RES_TYPES; enum misc_res_type type = MISC_CG_RES_TYPES;
char *token; char *token;
@ -271,7 +269,7 @@ static ssize_t misc_cg_max_write(struct kernfs_open_file *of, char *buf,
if (!strcmp(MAX_STR, buf)) { if (!strcmp(MAX_STR, buf)) {
max = MAX_NUM; max = MAX_NUM;
} else { } else {
ret = kstrtoul(buf, 0, &max); ret = kstrtou64(buf, 0, &max);
if (ret) if (ret)
return ret; return ret;
} }
@ -297,13 +295,13 @@ static ssize_t misc_cg_max_write(struct kernfs_open_file *of, char *buf,
static int misc_cg_current_show(struct seq_file *sf, void *v) static int misc_cg_current_show(struct seq_file *sf, void *v)
{ {
int i; int i;
unsigned long usage; u64 usage;
struct misc_cg *cg = css_misc(seq_css(sf)); struct misc_cg *cg = css_misc(seq_css(sf));
for (i = 0; i < MISC_CG_RES_TYPES; i++) { for (i = 0; i < MISC_CG_RES_TYPES; i++) {
usage = atomic_long_read(&cg->res[i].usage); usage = atomic64_read(&cg->res[i].usage);
if (READ_ONCE(misc_res_capacity[i]) || usage) if (READ_ONCE(misc_res_capacity[i]) || usage)
seq_printf(sf, "%s %lu\n", misc_res_name[i], usage); seq_printf(sf, "%s %llu\n", misc_res_name[i], usage);
} }
return 0; return 0;
@ -322,12 +320,12 @@ static int misc_cg_current_show(struct seq_file *sf, void *v)
static int misc_cg_capacity_show(struct seq_file *sf, void *v) static int misc_cg_capacity_show(struct seq_file *sf, void *v)
{ {
int i; int i;
unsigned long cap; u64 cap;
for (i = 0; i < MISC_CG_RES_TYPES; i++) { for (i = 0; i < MISC_CG_RES_TYPES; i++) {
cap = READ_ONCE(misc_res_capacity[i]); cap = READ_ONCE(misc_res_capacity[i]);
if (cap) if (cap)
seq_printf(sf, "%s %lu\n", misc_res_name[i], cap); seq_printf(sf, "%s %llu\n", misc_res_name[i], cap);
} }
return 0; return 0;
@ -336,12 +334,13 @@ static int misc_cg_capacity_show(struct seq_file *sf, void *v)
static int misc_events_show(struct seq_file *sf, void *v) static int misc_events_show(struct seq_file *sf, void *v)
{ {
struct misc_cg *cg = css_misc(seq_css(sf)); struct misc_cg *cg = css_misc(seq_css(sf));
unsigned long events, i; u64 events;
int i;
for (i = 0; i < MISC_CG_RES_TYPES; i++) { for (i = 0; i < MISC_CG_RES_TYPES; i++) {
events = atomic_long_read(&cg->res[i].events); events = atomic64_read(&cg->res[i].events);
if (READ_ONCE(misc_res_capacity[i]) || events) if (READ_ONCE(misc_res_capacity[i]) || events)
seq_printf(sf, "%s.max %lu\n", misc_res_name[i], events); seq_printf(sf, "%s.max %llu\n", misc_res_name[i], events);
} }
return 0; return 0;
} }
@ -397,7 +396,7 @@ misc_cg_alloc(struct cgroup_subsys_state *parent_css)
for (i = 0; i < MISC_CG_RES_TYPES; i++) { for (i = 0; i < MISC_CG_RES_TYPES; i++) {
WRITE_ONCE(cg->res[i].max, MAX_NUM); WRITE_ONCE(cg->res[i].max, MAX_NUM);
atomic_long_set(&cg->res[i].usage, 0); atomic64_set(&cg->res[i].usage, 0);
} }
return &cg->css; return &cg->css;