Commit 451af504 authored by Tejun Heo's avatar Tejun Heo

cgroup: replace cftype->write_string() with cftype->write()

Convert all cftype->write_string() users to the new cftype->write()
which maps directly to kernfs write operation and has full access to
kernfs and cgroup contexts.  The conversions are mostly mechanical.

* @css and @cft are accessed using of_css() and of_cft() accessors
  respectively instead of being specified as arguments.

* Should return @nbytes on success instead of 0.

* @buf is not trimmed automatically.  Trim if necessary.  Note that
  blkcg and netprio don't need this as the parsers already handle
  whitespaces.

cftype->write_string() has no user left after the conversions and
removed.

While at it, remove unnecessary local variable @p in
cgroup_subtree_control_write() and stale comment about
CGROUP_LOCAL_BUFFER_SIZE in cgroup_freezer.c.

This patch doesn't introduce any visible behavior changes.

v2: netprio was missing from conversion.  Converted.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarAristeu Rozanski <arozansk@redhat.com>
Acked-by: default avatarVivek Goyal <vgoyal@redhat.com>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: "David S. Miller" <davem@davemloft.net>
parent b4168640
...@@ -1346,10 +1346,10 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v) ...@@ -1346,10 +1346,10 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v)
return 0; return 0;
} }
static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, static ssize_t tg_set_conf(struct kernfs_open_file *of,
const char *buf, bool is_u64) char *buf, size_t nbytes, loff_t off, bool is_u64)
{ {
struct blkcg *blkcg = css_to_blkcg(css); struct blkcg *blkcg = css_to_blkcg(of_css(of));
struct blkg_conf_ctx ctx; struct blkg_conf_ctx ctx;
struct throtl_grp *tg; struct throtl_grp *tg;
struct throtl_service_queue *sq; struct throtl_service_queue *sq;
...@@ -1368,9 +1368,9 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, ...@@ -1368,9 +1368,9 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft,
ctx.v = -1; ctx.v = -1;
if (is_u64) if (is_u64)
*(u64 *)((void *)tg + cft->private) = ctx.v; *(u64 *)((void *)tg + of_cft(of)->private) = ctx.v;
else else
*(unsigned int *)((void *)tg + cft->private) = ctx.v; *(unsigned int *)((void *)tg + of_cft(of)->private) = ctx.v;
throtl_log(&tg->service_queue, throtl_log(&tg->service_queue,
"limit change rbps=%llu wbps=%llu riops=%u wiops=%u", "limit change rbps=%llu wbps=%llu riops=%u wiops=%u",
...@@ -1404,19 +1404,19 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, ...@@ -1404,19 +1404,19 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft,
} }
blkg_conf_finish(&ctx); blkg_conf_finish(&ctx);
return 0; return nbytes;
} }
static int tg_set_conf_u64(struct cgroup_subsys_state *css, struct cftype *cft, static ssize_t tg_set_conf_u64(struct kernfs_open_file *of,
char *buf) char *buf, size_t nbytes, loff_t off)
{ {
return tg_set_conf(css, cft, buf, true); return tg_set_conf(of, buf, nbytes, off, true);
} }
static int tg_set_conf_uint(struct cgroup_subsys_state *css, struct cftype *cft, static ssize_t tg_set_conf_uint(struct kernfs_open_file *of,
char *buf) char *buf, size_t nbytes, loff_t off)
{ {
return tg_set_conf(css, cft, buf, false); return tg_set_conf(of, buf, nbytes, off, false);
} }
static struct cftype throtl_files[] = { static struct cftype throtl_files[] = {
...@@ -1424,25 +1424,25 @@ static struct cftype throtl_files[] = { ...@@ -1424,25 +1424,25 @@ static struct cftype throtl_files[] = {
.name = "throttle.read_bps_device", .name = "throttle.read_bps_device",
.private = offsetof(struct throtl_grp, bps[READ]), .private = offsetof(struct throtl_grp, bps[READ]),
.seq_show = tg_print_conf_u64, .seq_show = tg_print_conf_u64,
.write_string = tg_set_conf_u64, .write = tg_set_conf_u64,
}, },
{ {
.name = "throttle.write_bps_device", .name = "throttle.write_bps_device",
.private = offsetof(struct throtl_grp, bps[WRITE]), .private = offsetof(struct throtl_grp, bps[WRITE]),
.seq_show = tg_print_conf_u64, .seq_show = tg_print_conf_u64,
.write_string = tg_set_conf_u64, .write = tg_set_conf_u64,
}, },
{ {
.name = "throttle.read_iops_device", .name = "throttle.read_iops_device",
.private = offsetof(struct throtl_grp, iops[READ]), .private = offsetof(struct throtl_grp, iops[READ]),
.seq_show = tg_print_conf_uint, .seq_show = tg_print_conf_uint,
.write_string = tg_set_conf_uint, .write = tg_set_conf_uint,
}, },
{ {
.name = "throttle.write_iops_device", .name = "throttle.write_iops_device",
.private = offsetof(struct throtl_grp, iops[WRITE]), .private = offsetof(struct throtl_grp, iops[WRITE]),
.seq_show = tg_print_conf_uint, .seq_show = tg_print_conf_uint,
.write_string = tg_set_conf_uint, .write = tg_set_conf_uint,
}, },
{ {
.name = "throttle.io_service_bytes", .name = "throttle.io_service_bytes",
......
...@@ -1670,11 +1670,11 @@ static int cfq_print_leaf_weight(struct seq_file *sf, void *v) ...@@ -1670,11 +1670,11 @@ static int cfq_print_leaf_weight(struct seq_file *sf, void *v)
return 0; return 0;
} }
static int __cfqg_set_weight_device(struct cgroup_subsys_state *css, static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
struct cftype *cft, const char *buf, char *buf, size_t nbytes, loff_t off,
bool is_leaf_weight) bool is_leaf_weight)
{ {
struct blkcg *blkcg = css_to_blkcg(css); struct blkcg *blkcg = css_to_blkcg(of_css(of));
struct blkg_conf_ctx ctx; struct blkg_conf_ctx ctx;
struct cfq_group *cfqg; struct cfq_group *cfqg;
int ret; int ret;
...@@ -1697,19 +1697,19 @@ static int __cfqg_set_weight_device(struct cgroup_subsys_state *css, ...@@ -1697,19 +1697,19 @@ static int __cfqg_set_weight_device(struct cgroup_subsys_state *css,
} }
blkg_conf_finish(&ctx); blkg_conf_finish(&ctx);
return ret; return ret ?: nbytes;
} }
static int cfqg_set_weight_device(struct cgroup_subsys_state *css, static ssize_t cfqg_set_weight_device(struct kernfs_open_file *of,
struct cftype *cft, char *buf) char *buf, size_t nbytes, loff_t off)
{ {
return __cfqg_set_weight_device(css, cft, buf, false); return __cfqg_set_weight_device(of, buf, nbytes, off, false);
} }
static int cfqg_set_leaf_weight_device(struct cgroup_subsys_state *css, static ssize_t cfqg_set_leaf_weight_device(struct kernfs_open_file *of,
struct cftype *cft, char *buf) char *buf, size_t nbytes, loff_t off)
{ {
return __cfqg_set_weight_device(css, cft, buf, true); return __cfqg_set_weight_device(of, buf, nbytes, off, true);
} }
static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft,
...@@ -1837,7 +1837,7 @@ static struct cftype cfq_blkcg_files[] = { ...@@ -1837,7 +1837,7 @@ static struct cftype cfq_blkcg_files[] = {
.name = "weight_device", .name = "weight_device",
.flags = CFTYPE_ONLY_ON_ROOT, .flags = CFTYPE_ONLY_ON_ROOT,
.seq_show = cfqg_print_leaf_weight_device, .seq_show = cfqg_print_leaf_weight_device,
.write_string = cfqg_set_leaf_weight_device, .write = cfqg_set_leaf_weight_device,
}, },
{ {
.name = "weight", .name = "weight",
...@@ -1851,7 +1851,7 @@ static struct cftype cfq_blkcg_files[] = { ...@@ -1851,7 +1851,7 @@ static struct cftype cfq_blkcg_files[] = {
.name = "weight_device", .name = "weight_device",
.flags = CFTYPE_NOT_ON_ROOT, .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = cfqg_print_weight_device, .seq_show = cfqg_print_weight_device,
.write_string = cfqg_set_weight_device, .write = cfqg_set_weight_device,
}, },
{ {
.name = "weight", .name = "weight",
...@@ -1863,7 +1863,7 @@ static struct cftype cfq_blkcg_files[] = { ...@@ -1863,7 +1863,7 @@ static struct cftype cfq_blkcg_files[] = {
{ {
.name = "leaf_weight_device", .name = "leaf_weight_device",
.seq_show = cfqg_print_leaf_weight_device, .seq_show = cfqg_print_leaf_weight_device,
.write_string = cfqg_set_leaf_weight_device, .write = cfqg_set_leaf_weight_device,
}, },
{ {
.name = "leaf_weight", .name = "leaf_weight",
......
...@@ -453,8 +453,7 @@ struct cftype { ...@@ -453,8 +453,7 @@ struct cftype {
/* /*
* The maximum length of string, excluding trailing nul, that can * The maximum length of string, excluding trailing nul, that can
* be passed to write_string. If < PAGE_SIZE-1, PAGE_SIZE-1 is * be passed to write. If < PAGE_SIZE-1, PAGE_SIZE-1 is assumed.
* assumed.
*/ */
size_t max_write_len; size_t max_write_len;
...@@ -500,13 +499,6 @@ struct cftype { ...@@ -500,13 +499,6 @@ struct cftype {
int (*write_s64)(struct cgroup_subsys_state *css, struct cftype *cft, int (*write_s64)(struct cgroup_subsys_state *css, struct cftype *cft,
s64 val); s64 val);
/*
* write_string() is passed a nul-terminated kernelspace
* buffer of maximum length determined by max_write_len.
* Returns 0 or -ve error code.
*/
int (*write_string)(struct cgroup_subsys_state *css, struct cftype *cft,
char *buffer);
/* /*
* trigger() callback can be used to get some kick from the * trigger() callback can be used to get some kick from the
* userspace, when the actual string written is not important * userspace, when the actual string written is not important
......
...@@ -1035,7 +1035,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft) ...@@ -1035,7 +1035,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
mode |= S_IRUGO; mode |= S_IRUGO;
if (cft->write_u64 || cft->write_s64 || cft->write || if (cft->write_u64 || cft->write_s64 || cft->write ||
cft->write_string || cft->trigger) cft->trigger)
mode |= S_IWUSR; mode |= S_IWUSR;
return mode; return mode;
...@@ -2352,20 +2352,21 @@ static int cgroup_procs_write(struct cgroup_subsys_state *css, ...@@ -2352,20 +2352,21 @@ static int cgroup_procs_write(struct cgroup_subsys_state *css,
return attach_task_by_pid(css->cgroup, tgid, true); return attach_task_by_pid(css->cgroup, tgid, true);
} }
static int cgroup_release_agent_write(struct cgroup_subsys_state *css, static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of,
struct cftype *cft, char *buffer) char *buf, size_t nbytes, loff_t off)
{ {
struct cgroup_root *root = css->cgroup->root; struct cgroup *cgrp = of_css(of)->cgroup;
struct cgroup_root *root = cgrp->root;
BUILD_BUG_ON(sizeof(root->release_agent_path) < PATH_MAX); BUILD_BUG_ON(sizeof(root->release_agent_path) < PATH_MAX);
if (!cgroup_lock_live_group(css->cgroup)) if (!cgroup_lock_live_group(cgrp))
return -ENODEV; return -ENODEV;
spin_lock(&release_agent_path_lock); spin_lock(&release_agent_path_lock);
strlcpy(root->release_agent_path, buffer, strlcpy(root->release_agent_path, strstrip(buf),
sizeof(root->release_agent_path)); sizeof(root->release_agent_path));
spin_unlock(&release_agent_path_lock); spin_unlock(&release_agent_path_lock);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
return 0; return nbytes;
} }
static int cgroup_release_agent_show(struct seq_file *seq, void *v) static int cgroup_release_agent_show(struct seq_file *seq, void *v)
...@@ -2530,21 +2531,22 @@ out_finish: ...@@ -2530,21 +2531,22 @@ out_finish:
} }
/* change the enabled child controllers for a cgroup in the default hierarchy */ /* change the enabled child controllers for a cgroup in the default hierarchy */
static int cgroup_subtree_control_write(struct cgroup_subsys_state *dummy_css, static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
struct cftype *cft, char *buffer) char *buf, size_t nbytes,
loff_t off)
{ {
unsigned int enable = 0, disable = 0; unsigned int enable = 0, disable = 0;
struct cgroup *cgrp = dummy_css->cgroup, *child; struct cgroup *cgrp = of_css(of)->cgroup, *child;
struct cgroup_subsys *ss; struct cgroup_subsys *ss;
char *tok, *p; char *tok;
int ssid, ret; int ssid, ret;
/* /*
* Parse input - space separated list of subsystem names prefixed * Parse input - space separated list of subsystem names prefixed
* with either + or -. * with either + or -.
*/ */
p = buffer; buf = strstrip(buf);
while ((tok = strsep(&p, " "))) { while ((tok = strsep(&buf, " "))) {
if (tok[0] == '\0') if (tok[0] == '\0')
continue; continue;
for_each_subsys(ss, ssid) { for_each_subsys(ss, ssid) {
...@@ -2692,7 +2694,7 @@ out_unlock_tree: ...@@ -2692,7 +2694,7 @@ out_unlock_tree:
out_unbreak: out_unbreak:
kernfs_unbreak_active_protection(cgrp->control_kn); kernfs_unbreak_active_protection(cgrp->control_kn);
cgroup_put(cgrp); cgroup_put(cgrp);
return ret; return ret ?: nbytes;
err_undo_css: err_undo_css:
cgrp->child_subsys_mask &= ~enable; cgrp->child_subsys_mask &= ~enable;
...@@ -2738,9 +2740,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, ...@@ -2738,9 +2740,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
css = cgroup_css(cgrp, cft->ss); css = cgroup_css(cgrp, cft->ss);
rcu_read_unlock(); rcu_read_unlock();
if (cft->write_string) { if (cft->write_u64) {
ret = cft->write_string(css, cft, strstrip(buf));
} else if (cft->write_u64) {
unsigned long long v; unsigned long long v;
ret = kstrtoull(buf, 0, &v); ret = kstrtoull(buf, 0, &v);
if (!ret) if (!ret)
...@@ -3984,7 +3984,7 @@ static struct cftype cgroup_base_files[] = { ...@@ -3984,7 +3984,7 @@ static struct cftype cgroup_base_files[] = {
.name = "cgroup.subtree_control", .name = "cgroup.subtree_control",
.flags = CFTYPE_ONLY_ON_DFL, .flags = CFTYPE_ONLY_ON_DFL,
.seq_show = cgroup_subtree_control_show, .seq_show = cgroup_subtree_control_show,
.write_string = cgroup_subtree_control_write, .write = cgroup_subtree_control_write,
}, },
{ {
.name = "cgroup.populated", .name = "cgroup.populated",
...@@ -4018,7 +4018,7 @@ static struct cftype cgroup_base_files[] = { ...@@ -4018,7 +4018,7 @@ static struct cftype cgroup_base_files[] = {
.name = "release_agent", .name = "release_agent",
.flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT, .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
.seq_show = cgroup_release_agent_show, .seq_show = cgroup_release_agent_show,
.write_string = cgroup_release_agent_write, .write = cgroup_release_agent_write,
.max_write_len = PATH_MAX - 1, .max_write_len = PATH_MAX - 1,
}, },
{ } /* terminate */ { } /* terminate */
......
...@@ -73,10 +73,6 @@ bool cgroup_freezing(struct task_struct *task) ...@@ -73,10 +73,6 @@ bool cgroup_freezing(struct task_struct *task)
return ret; return ret;
} }
/*
* cgroups_write_string() limits the size of freezer state strings to
* CGROUP_LOCAL_BUFFER_SIZE
*/
static const char *freezer_state_strs(unsigned int state) static const char *freezer_state_strs(unsigned int state)
{ {
if (state & CGROUP_FROZEN) if (state & CGROUP_FROZEN)
...@@ -423,20 +419,22 @@ static void freezer_change_state(struct freezer *freezer, bool freeze) ...@@ -423,20 +419,22 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
mutex_unlock(&freezer_mutex); mutex_unlock(&freezer_mutex);
} }
static int freezer_write(struct cgroup_subsys_state *css, struct cftype *cft, static ssize_t freezer_write(struct kernfs_open_file *of,
char *buffer) char *buf, size_t nbytes, loff_t off)
{ {
bool freeze; bool freeze;
if (strcmp(buffer, freezer_state_strs(0)) == 0) buf = strstrip(buf);
if (strcmp(buf, freezer_state_strs(0)) == 0)
freeze = false; freeze = false;
else if (strcmp(buffer, freezer_state_strs(CGROUP_FROZEN)) == 0) else if (strcmp(buf, freezer_state_strs(CGROUP_FROZEN)) == 0)
freeze = true; freeze = true;
else else
return -EINVAL; return -EINVAL;
freezer_change_state(css_freezer(css), freeze); freezer_change_state(css_freezer(of_css(of)), freeze);
return 0; return nbytes;
} }
static u64 freezer_self_freezing_read(struct cgroup_subsys_state *css, static u64 freezer_self_freezing_read(struct cgroup_subsys_state *css,
...@@ -460,7 +458,7 @@ static struct cftype files[] = { ...@@ -460,7 +458,7 @@ static struct cftype files[] = {
.name = "state", .name = "state",
.flags = CFTYPE_NOT_ON_ROOT, .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = freezer_read, .seq_show = freezer_read,
.write_string = freezer_write, .write = freezer_write,
}, },
{ {
.name = "self_freezing", .name = "self_freezing",
......
...@@ -1603,13 +1603,15 @@ out_unlock: ...@@ -1603,13 +1603,15 @@ out_unlock:
/* /*
* Common handling for a write to a "cpus" or "mems" file. * Common handling for a write to a "cpus" or "mems" file.
*/ */
static int cpuset_write_resmask(struct cgroup_subsys_state *css, static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
struct cftype *cft, char *buf) char *buf, size_t nbytes, loff_t off)
{ {
struct cpuset *cs = css_cs(css); struct cpuset *cs = css_cs(of_css(of));
struct cpuset *trialcs; struct cpuset *trialcs;
int retval = -ENODEV; int retval = -ENODEV;
buf = strstrip(buf);
/* /*
* CPU or memory hotunplug may leave @cs w/o any execution * CPU or memory hotunplug may leave @cs w/o any execution
* resources, in which case the hotplug code asynchronously updates * resources, in which case the hotplug code asynchronously updates
...@@ -1633,7 +1635,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css, ...@@ -1633,7 +1635,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css,
goto out_unlock; goto out_unlock;
} }
switch (cft->private) { switch (of_cft(of)->private) {
case FILE_CPULIST: case FILE_CPULIST:
retval = update_cpumask(cs, trialcs, buf); retval = update_cpumask(cs, trialcs, buf);
break; break;
...@@ -1648,7 +1650,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css, ...@@ -1648,7 +1650,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css,
free_trial_cpuset(trialcs); free_trial_cpuset(trialcs);
out_unlock: out_unlock:
mutex_unlock(&cpuset_mutex); mutex_unlock(&cpuset_mutex);
return retval; return retval ?: nbytes;
} }
/* /*
...@@ -1750,7 +1752,7 @@ static struct cftype files[] = { ...@@ -1750,7 +1752,7 @@ static struct cftype files[] = {
{ {
.name = "cpus", .name = "cpus",
.seq_show = cpuset_common_seq_show, .seq_show = cpuset_common_seq_show,
.write_string = cpuset_write_resmask, .write = cpuset_write_resmask,
.max_write_len = (100U + 6 * NR_CPUS), .max_write_len = (100U + 6 * NR_CPUS),
.private = FILE_CPULIST, .private = FILE_CPULIST,
}, },
...@@ -1758,7 +1760,7 @@ static struct cftype files[] = { ...@@ -1758,7 +1760,7 @@ static struct cftype files[] = {
{ {
.name = "mems", .name = "mems",
.seq_show = cpuset_common_seq_show, .seq_show = cpuset_common_seq_show,
.write_string = cpuset_write_resmask, .write = cpuset_write_resmask,
.max_write_len = (100U + 6 * MAX_NUMNODES), .max_write_len = (100U + 6 * MAX_NUMNODES),
.private = FILE_MEMLIST, .private = FILE_MEMLIST,
}, },
......
...@@ -253,15 +253,16 @@ static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css, ...@@ -253,15 +253,16 @@ static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,
return res_counter_read_u64(&h_cg->hugepage[idx], name); return res_counter_read_u64(&h_cg->hugepage[idx], name);
} }
static int hugetlb_cgroup_write(struct cgroup_subsys_state *css, static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,
struct cftype *cft, char *buffer) char *buf, size_t nbytes, loff_t off)
{ {
int idx, name, ret; int idx, name, ret;
unsigned long long val; unsigned long long val;
struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css); struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(of_css(of));
idx = MEMFILE_IDX(cft->private); buf = strstrip(buf);
name = MEMFILE_ATTR(cft->private); idx = MEMFILE_IDX(of_cft(of)->private);
name = MEMFILE_ATTR(of_cft(of)->private);
switch (name) { switch (name) {
case RES_LIMIT: case RES_LIMIT:
...@@ -271,7 +272,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css, ...@@ -271,7 +272,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css,
break; break;
} }
/* This function does all necessary parse...reuse it */ /* This function does all necessary parse...reuse it */
ret = res_counter_memparse_write_strategy(buffer, &val); ret = res_counter_memparse_write_strategy(buf, &val);
if (ret) if (ret)
break; break;
ret = res_counter_set_limit(&h_cg->hugepage[idx], val); ret = res_counter_set_limit(&h_cg->hugepage[idx], val);
...@@ -280,7 +281,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css, ...@@ -280,7 +281,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css,
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
return ret; return ret ?: nbytes;
} }
static int hugetlb_cgroup_reset(struct cgroup_subsys_state *css, static int hugetlb_cgroup_reset(struct cgroup_subsys_state *css,
...@@ -331,7 +332,7 @@ static void __init __hugetlb_cgroup_file_init(int idx) ...@@ -331,7 +332,7 @@ static void __init __hugetlb_cgroup_file_init(int idx)
snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf); snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf);
cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT); cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT);
cft->read_u64 = hugetlb_cgroup_read_u64; cft->read_u64 = hugetlb_cgroup_read_u64;
cft->write_string = hugetlb_cgroup_write; cft->write = hugetlb_cgroup_write;
/* Add the usage file */ /* Add the usage file */
cft = &h->cgroup_files[1]; cft = &h->cgroup_files[1];
......
...@@ -5143,17 +5143,18 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg, ...@@ -5143,17 +5143,18 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,
* The user of this function is... * The user of this function is...
* RES_LIMIT. * RES_LIMIT.
*/ */
static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, static ssize_t mem_cgroup_write(struct kernfs_open_file *of,
char *buffer) char *buf, size_t nbytes, loff_t off)
{ {
struct mem_cgroup *memcg = mem_cgroup_from_css(css); struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
enum res_type type; enum res_type type;
int name; int name;
unsigned long long val; unsigned long long val;
int ret; int ret;
type = MEMFILE_TYPE(cft->private); buf = strstrip(buf);
name = MEMFILE_ATTR(cft->private); type = MEMFILE_TYPE(of_cft(of)->private);
name = MEMFILE_ATTR(of_cft(of)->private);
switch (name) { switch (name) {
case RES_LIMIT: case RES_LIMIT:
...@@ -5162,7 +5163,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, ...@@ -5162,7 +5163,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft,
break; break;
} }
/* This function does all necessary parse...reuse it */ /* This function does all necessary parse...reuse it */
ret = res_counter_memparse_write_strategy(buffer, &val); ret = res_counter_memparse_write_strategy(buf, &val);
if (ret) if (ret)
break; break;
if (type == _MEM) if (type == _MEM)
...@@ -5175,7 +5176,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, ...@@ -5175,7 +5176,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft,
return -EINVAL; return -EINVAL;
break; break;
case RES_SOFT_LIMIT: case RES_SOFT_LIMIT:
ret = res_counter_memparse_write_strategy(buffer, &val); ret = res_counter_memparse_write_strategy(buf, &val);
if (ret) if (ret)
break; break;
/* /*
...@@ -5192,7 +5193,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, ...@@ -5192,7 +5193,7 @@ static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft,
ret = -EINVAL; /* should be BUG() ? */ ret = -EINVAL; /* should be BUG() ? */
break; break;
} }
return ret;