cgroup: implement cftype->write()
Subsystems (9)
Tejun Heo
maintainerPATCH 1/1 cgroup: implement cftype->write()
Hello,
This patchset implements a new cftype operation ->write() and replace ->write_string() and ->trigger() with it. ->write() is similar to ->write_string() but maps directly to the kernfs write operation and has access to all available context information including the associated kernfs_open_file, which will make things like implementing kernfs active protection manipulation easier.
->write_string() becomes redundant and ->trigger() has always been spurious. This patch replaces all users of the two methods to ->write() and remove them.
This patchset contains the following five patches.
0001-cgroup-implement-cftype-write.patch 0002-cgroup-replace-cftype-write_string-with-cftype-write.patch 0003-cgroup-replace-cftype-trigger-with-cftype-write.patch 0004-cgroup-convert-tasks-and-cgroup.procs-handle-to-use-.patch 0005-cgroup-remove-cgroup-control_kn.patch
0001 implements cftype->write().
0002-0003 replace cftype->write_string() and ->trigger() with it.
0004 convert "tasks" and "cgroup.procs" handler too.
0005 removes cgroup->control_kn as the kernfs_node is now directly accessible from kernfs_open_file.
This patchset is on top of
cgroup/for-3.16 12d3089c192c ("kernel/cpuset.c: convert printk to pr_foo()")
+ [1] [PATCHSET cgroup/for-3.16] cgroup: post unified hierarchy fixes and updates
and available on the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-post-unified-updates
diffstat follows.
block/blk-throttle.c | 32 ++++++++--------- block/cfq-iosched.c | 28 +++++++-------- include/linux/cgroup.h | 40 +++++++++++---------- kernel/cgroup.c | 85 +++++++++++++++++++++++----------------------- kernel/cgroup_freezer.c | 20 ++++------ kernel/cpuset.c | 16 ++++---- mm/hugetlb_cgroup.c | 33 +++++++++-------- mm/memcontrol.c | 80 +++++++++++++++++++++++-------------------- net/ipv4/tcp_memcontrol.c | 31 +++++++++------- security/device_cgroup.c | 14 +++---- 10 files changed, 197 insertions(+), 182 deletions(-)
Thanks.
--
tejun
Tejun Heo
maintainerPATCH 1/5 cgroup: implement cftype->write()
During the recent conversion to kernfs, cftype's seq_file operations are updated so that they are directly mapped to kernfs operations and thus can fully access the associated kernfs and cgroup contexts; however, write path hasn't seen similar updates and none of the existing write operations has access to, for example, the associated kernfs_open_file.
Let's introduce a new operation cftype->write() which maps directly to the kernfs write operation and has access to all the arguments and contexts. This will replace ->write_string() and ->trigger() and ease manipulation of kernfs active protection from cgroup file operations.
Two accessors - of_cft() and of_css() - are introduced to enable accessing the associated cgroup context from cftype->write() which only takes kernfs_open_file for the context information. The accessors for seq_file operations - seq_cft() and seq_css() - are rewritten to wrap the of_ accessors.
--- include/linux/cgroup.h | 27 +++++++++++++++++++++++---- kernel/cgroup.c | 14 ++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-)
include/linux/cgroup.h +23 -4
@@ -517,6 +517,15 @@ struct cftype {*/ int (*trigger)(struct cgroup_subsys_state *css,unsigned int event); +/* +* write() is the generic write callback which maps directly to +* kernfs write operation and overrides all other operations. +* Maximum write size is determined by ->max_write_len. Use +* of_css/cft() to access the associated css and cft. +*/ +ssize_t (*write)(struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off); +#ifdef CONFIG_DEBUG_LOCK_ALLOC struct lock_class_key lockdep_key;#endif
@@ -553,14 +562,24 @@ static inline ino_t cgroup_ino(struct cgroup *cgrp)return 0 ; } -static inline struct cftype *seq_cft (struct seq_file *seq) +/* cft/css accessors for cftype->write() operation */ +static inline struct cftype *of_cft (struct kernfs_open_file *of) { -struct kernfs_open_file *of = seq->private; -return of->kn->priv; } -struct cgroup_subsys_state *seq_css (struct seq_file *seq); +struct cgroup_subsys_state *of_css (struct kernfs_open_file *of); + +/* cft/css accessors for cftype->seq_*() operations */ +static inline struct cftype *seq_cft (struct seq_file *seq) +{ +return of_cft (seq->private); +} + +static inline struct cgroup_subsys_state *seq_css (struct seq_file *seq) +{ +return of_css (seq->private); +}/* * Name / path handling functions. All are thin wrappers around the kernfs
kernel/cgroup.c +8 -6
@@ -283,11 +283,10 @@ static inline bool cgroup_is_dead(const struct cgroup *cgrp)return test_bit (CGRP_DEAD , &cgrp->flags); } -struct cgroup_subsys_state *seq_css (struct seq_file *seq) +struct cgroup_subsys_state *of_css (struct kernfs_open_file *of) { -struct kernfs_open_file *of = seq->private;struct cgroup *cgrp = of->kn->parent->priv; -struct cftype *cft =seq_cft (seq); +struct cftype *cft =of_cft (of);/* * This is open and unprotected implementation of cgroup_css().
@@ -302,7 +301,7 @@ struct cgroup_subsys_state *seq_css(struct seq_file *seq)else return &cgrp->dummy_css; } -EXPORT_SYMBOL_GPL (seq_css); +EXPORT_SYMBOL_GPL (of_css);/** * cgroup_is_descendant - test ancestry
@@ -1035,8 +1034,8 @@ static umode_t cgroup_file_mode(const struct cftype *cft)if (cft->read_u64 || cft->read_s64 || cft->seq_show) mode |=S_IRUGO ; -if (cft->write_u64 || cft->write_s64 || cft->write_string || - cft->trigger) +if (cft->write_u64 || cft->write_s64 || cft->write || + cft->write_string || cft->trigger) mode |=S_IWUSR ;return mode;
@@ -2724,6 +2723,9 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,struct cgroup_subsys_state *css;int ret; +if (cft->write) +return cft->write (of, buf, nbytes, off); +/* * kernfs guarantees that a file isn't deleted with operations in * flight, which means that the matching css is and stays alive and
Signature · 1 line
1.9.0
Tejun Heo
maintainerPATCH 2/5 cgroup: replace cftype->write_string() with cftype->write()
In reply to Tejun HeoConvert 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 doesn't need this as blkg_conf_prep() can 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.
--- block/blk-throttle.c | 32 ++++++++++++++++---------------- block/cfq-iosched.c | 28 ++++++++++++++-------------- include/linux/cgroup.h | 10 +--------- kernel/cgroup.c | 38 +++++++++++++++++++------------------- kernel/cgroup_freezer.c | 20 +++++++++----------- kernel/cpuset.c | 16 +++++++++------- mm/hugetlb_cgroup.c | 17 +++++++++-------- mm/memcontrol.c | 46 +++++++++++++++++++++++++--------------------- net/ipv4/tcp_memcontrol.c | 16 +++++++++------- security/device_cgroup.c | 14 +++++++------- 10 files changed, 118 insertions(+), 119 deletions(-)
block/blk-throttle.c +16 -16
@@ -1346,10 +1346,10 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v)return 0 ; } -static int tg_set_conf (struct cgroup_subsys_state *css,struct cftype *cft, -const char *buf,bool is_u64) +static ssize_t tg_set_conf (struct kernfs_open_file *of, +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 throtl_grp *tg;struct throtl_service_queue *sq;
@@ -1368,9 +1368,9 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, ctx.v =-1 ;if (is_u64) - *(u64 *)((void *)tg + cft->private) = ctx.v; + *(u64 *)((void *)tg +of_cft (of)->private) = ctx.v;else - *(unsigned int *)((void *)tg + cft->private) = ctx.v; + *(unsigned int *)((void *)tg +of_cft (of)->private) = ctx.v; throtl_log(&tg->service_queue, "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, }blkg_conf_finish (&ctx); -return 0 ; +return nbytes; } -static int tg_set_conf_u64 (struct cgroup_subsys_state *css,struct cftype *cft, -char *buf) +static ssize_t tg_set_conf_u64 (struct kernfs_open_file *of, +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, -char *buf) +static ssize_t tg_set_conf_uint (struct kernfs_open_file *of, +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[] = {
@@ -1424,25 +1424,25 @@ static struct cftype throtl_files[] = { .name = "throttle.read_bps_device", .private = offsetof(struct throtl_grp, bps[READ]), .seq_show = tg_print_conf_u64, - .write_string = tg_set_conf_u64, + .write = tg_set_conf_u64, }, { .name = "throttle.write_bps_device", .private = offsetof(struct throtl_grp, bps[WRITE]), .seq_show = tg_print_conf_u64, - .write_string = tg_set_conf_u64, + .write = tg_set_conf_u64, }, { .name = "throttle.read_iops_device", .private = offsetof(struct throtl_grp, iops[READ]), .seq_show = tg_print_conf_uint, - .write_string = tg_set_conf_uint, + .write = tg_set_conf_uint, }, { .name = "throttle.write_iops_device", .private = offsetof(struct throtl_grp, iops[WRITE]), .seq_show = tg_print_conf_uint, - .write_string = tg_set_conf_uint, + .write = tg_set_conf_uint, }, { .name = "throttle.io_service_bytes",
block/cfq-iosched.c +14 -14
@@ -1670,11 +1670,11 @@ static int cfq_print_leaf_weight(struct seq_file *sf, void *v)return 0 ; } -static int __cfqg_set_weight_device (struct cgroup_subsys_state *css, -struct cftype *cft,const char *buf, -bool is_leaf_weight) +static ssize_t __cfqg_set_weight_device (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off, +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 cfq_group *cfqg;int ret;
@@ -1697,19 +1697,19 @@ static int __cfqg_set_weight_device(struct cgroup_subsys_state *css, }blkg_conf_finish (&ctx); -return ret; +return ret ?: nbytes; } -static int cfqg_set_weight_device (struct cgroup_subsys_state *css, -struct cftype *cft,char *buf) +static ssize_t cfqg_set_weight_device (struct kernfs_open_file *of, +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, -struct cftype *cft,char *buf) +static ssize_t cfqg_set_leaf_weight_device (struct kernfs_open_file *of, +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,
@@ -1837,7 +1837,7 @@ static struct cftype cfq_blkcg_files[] = { .name = "weight_device", .flags = CFTYPE_ONLY_ON_ROOT, .seq_show = cfqg_print_leaf_weight_device, - .write_string = cfqg_set_leaf_weight_device, + .write = cfqg_set_leaf_weight_device, }, { .name = "weight",
@@ -1851,7 +1851,7 @@ static struct cftype cfq_blkcg_files[] = { .name = "weight_device", .flags = CFTYPE_NOT_ON_ROOT, .seq_show = cfqg_print_weight_device, - .write_string = cfqg_set_weight_device, + .write = cfqg_set_weight_device, }, { .name = "weight",
@@ -1863,7 +1863,7 @@ static struct cftype cfq_blkcg_files[] = { { .name = "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",
include/linux/cgroup.h +1 -9
@@ -455,8 +455,7 @@ struct cftype {/* * The maximum length of string, excluding trailing nul, that can -* be passed to write_string. If < PAGE_SIZE-1, PAGE_SIZE-1 is -* assumed. +* be passed to write. If < PAGE_SIZE-1, PAGE_SIZE-1 is assumed. */ size_t max_write_len;
@@ -503,13 +502,6 @@ struct cftype { 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 * userspace, when the actual string written is not important * at all. The private field can be used to determine the
kernel/cgroup.c +19 -19
@@ -1035,7 +1035,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft) mode |=S_IRUGO ;if (cft->write_u64 || cft->write_s64 || cft->write || - cft->write_string || cft->trigger) + cft->trigger) mode |=S_IWUSR ;return mode;
@@ -2352,20 +2352,21 @@ static int cgroup_procs_write(struct cgroup_subsys_state *css,return attach_task_by_pid (css->cgroup, tgid, true); } -static int cgroup_release_agent_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t cgroup_release_agent_write (struct kernfs_open_file *of, +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 ); -if (!cgroup_lock_live_group (css->cgroup)) +if (!cgroup_lock_live_group (cgrp))return -ENODEV ;spin_lock (&release_agent_path_lock); -strlcpy (root->release_agent_path, buffer, +strlcpy (root->release_agent_path,strstrip (buf),sizeof (root->release_agent_path));spin_unlock (&release_agent_path_lock);mutex_unlock (&cgroup_mutex); -return 0 ; +return nbytes; }static int cgroup_release_agent_show (struct seq_file *seq,void *v)
@@ -2530,21 +2531,22 @@ out_finish: }/* change the enabled child controllers for a cgroup in the default hierarchy */ -static int cgroup_subtree_control_write (struct cgroup_subsys_state *dummy_css, -struct cftype *cft,char *buffer) +static ssize_t cgroup_subtree_control_write (struct kernfs_open_file *of, +char *buf,size_t nbytes, +loff_t off) {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; -char *tok, *p; +char *tok;int ssid, ret;/* * Parse input - space separated list of subsystem names prefixed * with either + or -. */ - p = buffer; -while ((tok =strsep (&p," " ))) { + buf =strstrip (buf); +while ((tok =strsep (&buf," " ))) {for_each_subsys (ss, ssid) {if (ss->disabled ||strcmp (tok +1 , ss->name))continue ;
@@ -2690,7 +2692,7 @@ out_unlock_tree: out_unbreak:kernfs_unbreak_active_protection (cgrp->control_kn);cgroup_put (cgrp); -return ret; +return ret ?: nbytes; err_undo_css: cgrp->child_subsys_mask &= ~enable;
@@ -2736,9 +2738,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, css =cgroup_css (cgrp, cft->ss);rcu_read_unlock (); -if (cft->write_string) { - ret = cft->write_string (css, cft,strstrip (buf)); - }else if (cft->write_u64) { +if (cft->write_u64) {unsigned long long v; ret =kstrtoull (buf,0 , &v);if (!ret)
@@ -3982,7 +3982,7 @@ static struct cftype cgroup_base_files[] = { .name = "cgroup.subtree_control", .flags = CFTYPE_ONLY_ON_DFL, .seq_show = cgroup_subtree_control_show, - .write_string = cgroup_subtree_control_write, + .write = cgroup_subtree_control_write, }, { .name = "cgroup.populated",
@@ -4016,7 +4016,7 @@ static struct cftype cgroup_base_files[] = { .name = "release_agent", .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT, .seq_show = cgroup_release_agent_show, - .write_string = cgroup_release_agent_write, + .write = cgroup_release_agent_write, .max_write_len = PATH_MAX - 1, }, { }/* terminate */
kernel/cgroup_freezer.c +9 -11
@@ -71,10 +71,6 @@ bool cgroup_freezing(struct task_struct *task)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) {if (state &CGROUP_FROZEN )
@@ -441,20 +437,22 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)rcu_read_unlock (); } -static int freezer_write (struct cgroup_subsys_state *css,struct cftype *cft, -char *buffer) +static ssize_t freezer_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {bool freeze; -if (strcmp (buffer,freezer_state_strs (0 )) ==0 ) + buf =strstrip (buf); + +if (strcmp (buf,freezer_state_strs (0 )) ==0 ) freeze = false; -else if (strcmp (buffer,freezer_state_strs (CGROUP_FROZEN )) ==0 ) +else if (strcmp (buf,freezer_state_strs (CGROUP_FROZEN )) ==0 ) freeze = true;else return -EINVAL ; -freezer_change_state (css_freezer (css), freeze); -return 0 ; +freezer_change_state (css_freezer (of_css (of)), freeze); +return nbytes; } static u64 freezer_self_freezing_read(struct cgroup_subsys_state *css,
@@ -478,7 +476,7 @@ static struct cftype files[] = { .name = "state", .flags = CFTYPE_NOT_ON_ROOT, .seq_show = freezer_read, - .write_string = freezer_write, + .write = freezer_write, }, { .name = "self_freezing",
kernel/cpuset.c +9 -7
@@ -1603,13 +1603,15 @@ out_unlock:/* * Common handling for a write to a "cpus" or "mems" file. */ -static int cpuset_write_resmask (struct cgroup_subsys_state *css, -struct cftype *cft,char *buf) +static ssize_t cpuset_write_resmask (struct kernfs_open_file *of, +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;int retval = -ENODEV ; + buf =strstrip (buf); +/* * CPU or memory hotunplug may leave @cs w/o any execution * resources, in which case the hotplug code asynchronously updates
@@ -1633,7 +1635,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css, goto out_unlock; } -switch (cft->private) { +switch (of_cft (of)->private) {case FILE_CPULIST : retval =update_cpumask (cs, trialcs, buf);break ;
@@ -1648,7 +1650,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css,free_trial_cpuset (trialcs); out_unlock:mutex_unlock (&cpuset_mutex); -return retval; +return retval ?: nbytes; }/*
@@ -1750,7 +1752,7 @@ static struct cftype files[] = { { .name = "cpus", .seq_show = cpuset_common_seq_show, - .write_string = cpuset_write_resmask, + .write = cpuset_write_resmask, .max_write_len = (100U + 6 * NR_CPUS), .private = FILE_CPULIST, },
@@ -1758,7 +1760,7 @@ static struct cftype files[] = { { .name = "mems", .seq_show = cpuset_common_seq_show, - .write_string = cpuset_write_resmask, + .write = cpuset_write_resmask, .max_write_len = (100U + 6 * MAX_NUMNODES), .private = FILE_MEMLIST, },
mm/hugetlb_cgroup.c +9 -8
@@ -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); } -static int hugetlb_cgroup_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t hugetlb_cgroup_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int idx, name, ret;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); - name =MEMFILE_ATTR (cft->private); + buf =strstrip (buf); + idx =MEMFILE_IDX (of_cft (of)->private); + name =MEMFILE_ATTR (of_cft (of)->private);switch (name) {case RES_LIMIT :
@@ -271,7 +272,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css,break ; }/* 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)break ; ret =res_counter_set_limit (&h_cg->hugepage[idx], val);
@@ -280,7 +281,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css, ret = -EINVAL ;break ; } -return ret; +return ret ?: nbytes; } static int hugetlb_cgroup_reset(struct cgroup_subsys_state *css,
@@ -331,7 +332,7 @@ static void __init __hugetlb_cgroup_file_init(int idx)snprintf (cft->name,MAX_CFTYPE_NAME ,"%s.limit_in_bytes" , buf); cft->private =MEMFILE_PRIVATE (idx,RES_LIMIT ); cft->read_u64 = hugetlb_cgroup_read_u64; - cft->write_string = hugetlb_cgroup_write; + cft->write = hugetlb_cgroup_write;/* Add the usage file */ cft = &h->cgroup_files[1 ];
mm/memcontrol.c +25 -21
135 lines not on this page · raw message
net/ipv4/tcp_memcontrol.c +9 -7
@@ -102,17 +102,19 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)return 0 ; } -static int tcp_cgroup_write (struct cgroup_subsys_state *css,struct cftype *cft, -char *buffer) +static ssize_t tcp_cgroup_write (struct kernfs_open_file *of, +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));unsigned long long val;int ret =0 ; -switch (cft->private) { + buf =strstrip (buf); + +switch (of_cft (of)->private) {case RES_LIMIT :/* see memcontrol.c */ - ret =res_counter_memparse_write_strategy (buffer, &val); + ret =res_counter_memparse_write_strategy (buf, &val);if (ret)break ; ret =tcp_update_limit (memcg, val);
@@ -121,7 +123,7 @@ static int tcp_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, ret = -EINVAL ;break ; } -return ret; +return ret ?: nbytes; }static u64 tcp_read_stat (struct mem_cgroup *memcg,int type,u64 default_val)
@@ -193,7 +195,7 @@ static int tcp_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event)static struct cftype tcp_files[] = { { .name ="kmem.tcp.limit_in_bytes" , - .write_string = tcp_cgroup_write, + .write = tcp_cgroup_write, .read_u64 = tcp_cgroup_read, .private =RES_LIMIT , },
security/device_cgroup.c +7 -7
@@ -651,27 +651,27 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,return rc; } -static int devcgroup_access_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t devcgroup_access_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int retval;mutex_lock (&devcgroup_mutex); - retval =devcgroup_update_access (css_to_devcgroup (css), - cft->private, buffer); + retval =devcgroup_update_access (css_to_devcgroup (of_css (of)), +of_cft (of)->private,strstrip (buf));mutex_unlock (&devcgroup_mutex); -return retval; +return retval ?: nbytes; }static struct cftype dev_cgroup_files[] = { { .name ="allow" , - .write_string = devcgroup_access_write, + .write = devcgroup_access_write, .private =DEVCG_ALLOW , }, { .name ="deny" , - .write_string = devcgroup_access_write, + .write = devcgroup_access_write, .private =DEVCG_DENY , }, {
Signature · 1 line
1.9.0
Re: [PATCH 2/5] cgroup: replace cftype->write_string() with cftype->write()
Quoted 41 lines · Tejun Heo
Convert all
cftype->write_string()users to the newcftype->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()andof_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 doesn't need this as
blkg_conf_prep()can 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 aboutCGROUP_LOCAL_BUFFER_SIZEincgroup_freezer.c.This patch doesn't introduce any visible behavior changes.
Signed-off-by Tejun Heo <[email protected]>Cc Vivek Goyal <[email protected]>Cc Jens Axboe <[email protected]>Cc Li Zefan <[email protected]>Cc Johannes Weiner <[email protected]>Cc Michal Hocko <[email protected]>Cc Aristeu Rozanski <[email protected]>--- block/blk-throttle.c | 32 ++++++++++++++++---------------- block/cfq-iosched.c | 28 ++++++++++++++-------------- include/linux/cgroup.h | 10 +--------- kernel/cgroup.c | 38 +++++++++++++++++++------------------- kernel/cgroup_freezer.c | 20 +++++++++----------- kernel/cpuset.c | 16 +++++++++------- mm/hugetlb_cgroup.c | 17 +++++++++-------- mm/memcontrol.c | 46 +++++++++++++++++++++++++--------------------- net/ipv4/tcp_memcontrol.c | 16 +++++++++------- security/device_cgroup.c | 14 +++++++------- 10 files changed, 118 insertions(+), 119 deletions(-)
(...)
Quoted 29 lines
security/device_cgroup.c +5
-6@@ -651,27 +651,27 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,return rc; } -static int devcgroup_access_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t devcgroup_access_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int retval;mutex_lock (&devcgroup_mutex); - retval =devcgroup_update_access (css_to_devcgroup (css), - cft->private, buffer); + retval =devcgroup_update_access (css_to_devcgroup (of_css (of)), +of_cft (of)->private,strstrip (buf));mutex_unlock (&devcgroup_mutex); -return retval; +return retval ?: nbytes; }static struct cftype dev_cgroup_files[] = { { .name ="allow" , - .write_string = devcgroup_access_write,
security/device_cgroup.c static int devcgroup_update_access(struct dev_cgroup *devcgroup, · line 677
Quoted 10 lines
security/device_cgroup.c +2
-1+ .write = devcgroup_access_write, .private = DEVCG_ALLOW, }, { .name = "deny", - .write_string = devcgroup_access_write, + .write = devcgroup_access_write, .private = DEVCG_DENY, }, {
for the device_cgroup part
Signature · 1 line
Aristeu
Tejun Heo
maintainerPATCH v2 2/5 cgroup: replace cftype->write_string() with cftype->write()
In reply to Tejun HeoConvert 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.
--- block/blk-throttle.c | 32 ++++++++++++++++---------------- block/cfq-iosched.c | 28 ++++++++++++++-------------- include/linux/cgroup.h | 10 +--------- kernel/cgroup.c | 38 +++++++++++++++++++------------------- kernel/cgroup_freezer.c | 20 +++++++++----------- kernel/cpuset.c | 16 +++++++++------- mm/hugetlb_cgroup.c | 17 +++++++++-------- mm/memcontrol.c | 46 +++++++++++++++++++++++++--------------------- net/core/netprio_cgroup.c | 12 ++++++------ net/ipv4/tcp_memcontrol.c | 16 +++++++++------- security/device_cgroup.c | 14 +++++++------- 11 files changed, 124 insertions(+), 125 deletions(-)
block/blk-throttle.c +16 -16
@@ -1346,10 +1346,10 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v)return 0 ; } -static int tg_set_conf (struct cgroup_subsys_state *css,struct cftype *cft, -const char *buf,bool is_u64) +static ssize_t tg_set_conf (struct kernfs_open_file *of, +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 throtl_grp *tg;struct throtl_service_queue *sq;
@@ -1368,9 +1368,9 @@ static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, ctx.v =-1 ;if (is_u64) - *(u64 *)((void *)tg + cft->private) = ctx.v; + *(u64 *)((void *)tg +of_cft (of)->private) = ctx.v;else - *(unsigned int *)((void *)tg + cft->private) = ctx.v; + *(unsigned int *)((void *)tg +of_cft (of)->private) = ctx.v; throtl_log(&tg->service_queue, "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, }blkg_conf_finish (&ctx); -return 0 ; +return nbytes; } -static int tg_set_conf_u64 (struct cgroup_subsys_state *css,struct cftype *cft, -char *buf) +static ssize_t tg_set_conf_u64 (struct kernfs_open_file *of, +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, -char *buf) +static ssize_t tg_set_conf_uint (struct kernfs_open_file *of, +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[] = {
@@ -1424,25 +1424,25 @@ static struct cftype throtl_files[] = { .name = "throttle.read_bps_device", .private = offsetof(struct throtl_grp, bps[READ]), .seq_show = tg_print_conf_u64, - .write_string = tg_set_conf_u64, + .write = tg_set_conf_u64, }, { .name = "throttle.write_bps_device", .private = offsetof(struct throtl_grp, bps[WRITE]), .seq_show = tg_print_conf_u64, - .write_string = tg_set_conf_u64, + .write = tg_set_conf_u64, }, { .name = "throttle.read_iops_device", .private = offsetof(struct throtl_grp, iops[READ]), .seq_show = tg_print_conf_uint, - .write_string = tg_set_conf_uint, + .write = tg_set_conf_uint, }, { .name = "throttle.write_iops_device", .private = offsetof(struct throtl_grp, iops[WRITE]), .seq_show = tg_print_conf_uint, - .write_string = tg_set_conf_uint, + .write = tg_set_conf_uint, }, { .name = "throttle.io_service_bytes",
block/cfq-iosched.c +14 -14
@@ -1670,11 +1670,11 @@ static int cfq_print_leaf_weight(struct seq_file *sf, void *v)return 0 ; } -static int __cfqg_set_weight_device (struct cgroup_subsys_state *css, -struct cftype *cft,const char *buf, -bool is_leaf_weight) +static ssize_t __cfqg_set_weight_device (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off, +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 cfq_group *cfqg;int ret;
@@ -1697,19 +1697,19 @@ static int __cfqg_set_weight_device(struct cgroup_subsys_state *css, }blkg_conf_finish (&ctx); -return ret; +return ret ?: nbytes; } -static int cfqg_set_weight_device (struct cgroup_subsys_state *css, -struct cftype *cft,char *buf) +static ssize_t cfqg_set_weight_device (struct kernfs_open_file *of, +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, -struct cftype *cft,char *buf) +static ssize_t cfqg_set_leaf_weight_device (struct kernfs_open_file *of, +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,
@@ -1837,7 +1837,7 @@ static struct cftype cfq_blkcg_files[] = { .name = "weight_device", .flags = CFTYPE_ONLY_ON_ROOT, .seq_show = cfqg_print_leaf_weight_device, - .write_string = cfqg_set_leaf_weight_device, + .write = cfqg_set_leaf_weight_device, }, { .name = "weight",
@@ -1851,7 +1851,7 @@ static struct cftype cfq_blkcg_files[] = { .name = "weight_device", .flags = CFTYPE_NOT_ON_ROOT, .seq_show = cfqg_print_weight_device, - .write_string = cfqg_set_weight_device, + .write = cfqg_set_weight_device, }, { .name = "weight",
@@ -1863,7 +1863,7 @@ static struct cftype cfq_blkcg_files[] = { { .name = "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",
include/linux/cgroup.h +1 -9
@@ -455,8 +455,7 @@ struct cftype {/* * The maximum length of string, excluding trailing nul, that can -* be passed to write_string. If < PAGE_SIZE-1, PAGE_SIZE-1 is -* assumed. +* be passed to write. If < PAGE_SIZE-1, PAGE_SIZE-1 is assumed. */ size_t max_write_len;
@@ -503,13 +502,6 @@ struct cftype { 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 * userspace, when the actual string written is not important * at all. The private field can be used to determine the
kernel/cgroup.c +19 -19
@@ -1035,7 +1035,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft) mode |=S_IRUGO ;if (cft->write_u64 || cft->write_s64 || cft->write || - cft->write_string || cft->trigger) + cft->trigger) mode |=S_IWUSR ;return mode;
@@ -2352,20 +2352,21 @@ static int cgroup_procs_write(struct cgroup_subsys_state *css,return attach_task_by_pid (css->cgroup, tgid, true); } -static int cgroup_release_agent_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t cgroup_release_agent_write (struct kernfs_open_file *of, +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 ); -if (!cgroup_lock_live_group (css->cgroup)) +if (!cgroup_lock_live_group (cgrp))return -ENODEV ;spin_lock (&release_agent_path_lock); -strlcpy (root->release_agent_path, buffer, +strlcpy (root->release_agent_path,strstrip (buf),sizeof (root->release_agent_path));spin_unlock (&release_agent_path_lock);mutex_unlock (&cgroup_mutex); -return 0 ; +return nbytes; }static int cgroup_release_agent_show (struct seq_file *seq,void *v)
@@ -2530,21 +2531,22 @@ out_finish: }/* change the enabled child controllers for a cgroup in the default hierarchy */ -static int cgroup_subtree_control_write (struct cgroup_subsys_state *dummy_css, -struct cftype *cft,char *buffer) +static ssize_t cgroup_subtree_control_write (struct kernfs_open_file *of, +char *buf,size_t nbytes, +loff_t off) {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; -char *tok, *p; +char *tok;int ssid, ret;/* * Parse input - space separated list of subsystem names prefixed * with either + or -. */ - p = buffer; -while ((tok =strsep (&p," " ))) { + buf =strstrip (buf); +while ((tok =strsep (&buf," " ))) {if (tok[0 ] =='\0' )continue ;for_each_subsys (ss, ssid) {
@@ -2692,7 +2694,7 @@ out_unlock_tree: out_unbreak:kernfs_unbreak_active_protection (cgrp->control_kn);cgroup_put (cgrp); -return ret; +return ret ?: nbytes; err_undo_css: cgrp->child_subsys_mask &= ~enable;
@@ -2738,9 +2740,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, css =cgroup_css (cgrp, cft->ss);rcu_read_unlock (); -if (cft->write_string) { - ret = cft->write_string (css, cft,strstrip (buf)); - }else if (cft->write_u64) { +if (cft->write_u64) {unsigned long long v; ret =kstrtoull (buf,0 , &v);if (!ret)
@@ -3984,7 +3984,7 @@ static struct cftype cgroup_base_files[] = { .name = "cgroup.subtree_control", .flags = CFTYPE_ONLY_ON_DFL, .seq_show = cgroup_subtree_control_show, - .write_string = cgroup_subtree_control_write, + .write = cgroup_subtree_control_write, }, { .name = "cgroup.populated",
@@ -4018,7 +4018,7 @@ static struct cftype cgroup_base_files[] = { .name = "release_agent", .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT, .seq_show = cgroup_release_agent_show, - .write_string = cgroup_release_agent_write, + .write = cgroup_release_agent_write, .max_write_len = PATH_MAX - 1, }, { }/* terminate */
kernel/cgroup_freezer.c +9 -11
@@ -71,10 +71,6 @@ bool cgroup_freezing(struct task_struct *task)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) {if (state &CGROUP_FROZEN )
@@ -441,20 +437,22 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)rcu_read_unlock (); } -static int freezer_write (struct cgroup_subsys_state *css,struct cftype *cft, -char *buffer) +static ssize_t freezer_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {bool freeze; -if (strcmp (buffer,freezer_state_strs (0 )) ==0 ) + buf =strstrip (buf); + +if (strcmp (buf,freezer_state_strs (0 )) ==0 ) freeze = false; -else if (strcmp (buffer,freezer_state_strs (CGROUP_FROZEN )) ==0 ) +else if (strcmp (buf,freezer_state_strs (CGROUP_FROZEN )) ==0 ) freeze = true;else return -EINVAL ; -freezer_change_state (css_freezer (css), freeze); -return 0 ; +freezer_change_state (css_freezer (of_css (of)), freeze); +return nbytes; } static u64 freezer_self_freezing_read(struct cgroup_subsys_state *css,
@@ -478,7 +476,7 @@ static struct cftype files[] = { .name = "state", .flags = CFTYPE_NOT_ON_ROOT, .seq_show = freezer_read, - .write_string = freezer_write, + .write = freezer_write, }, { .name = "self_freezing",
kernel/cpuset.c +9 -7
@@ -1603,13 +1603,15 @@ out_unlock:/* * Common handling for a write to a "cpus" or "mems" file. */ -static int cpuset_write_resmask (struct cgroup_subsys_state *css, -struct cftype *cft,char *buf) +static ssize_t cpuset_write_resmask (struct kernfs_open_file *of, +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;int retval = -ENODEV ; + buf =strstrip (buf); +/* * CPU or memory hotunplug may leave @cs w/o any execution * resources, in which case the hotplug code asynchronously updates
@@ -1633,7 +1635,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css, goto out_unlock; } -switch (cft->private) { +switch (of_cft (of)->private) {case FILE_CPULIST : retval =update_cpumask (cs, trialcs, buf);break ;
@@ -1648,7 +1650,7 @@ static int cpuset_write_resmask(struct cgroup_subsys_state *css,free_trial_cpuset (trialcs); out_unlock:mutex_unlock (&cpuset_mutex); -return retval; +return retval ?: nbytes; }/*
@@ -1750,7 +1752,7 @@ static struct cftype files[] = { { .name = "cpus", .seq_show = cpuset_common_seq_show, - .write_string = cpuset_write_resmask, + .write = cpuset_write_resmask, .max_write_len = (100U + 6 * NR_CPUS), .private = FILE_CPULIST, },
@@ -1758,7 +1760,7 @@ static struct cftype files[] = { { .name = "mems", .seq_show = cpuset_common_seq_show, - .write_string = cpuset_write_resmask, + .write = cpuset_write_resmask, .max_write_len = (100U + 6 * MAX_NUMNODES), .private = FILE_MEMLIST, },
mm/hugetlb_cgroup.c +9 -8
@@ -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); } -static int hugetlb_cgroup_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t hugetlb_cgroup_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int idx, name, ret;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); - name =MEMFILE_ATTR (cft->private); + buf =strstrip (buf); + idx =MEMFILE_IDX (of_cft (of)->private); + name =MEMFILE_ATTR (of_cft (of)->private);switch (name) {case RES_LIMIT :
@@ -271,7 +272,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css,break ; }/* 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)break ; ret =res_counter_set_limit (&h_cg->hugepage[idx], val);
@@ -280,7 +281,7 @@ static int hugetlb_cgroup_write(struct cgroup_subsys_state *css, ret = -EINVAL ;break ; } -return ret; +return ret ?: nbytes; } static int hugetlb_cgroup_reset(struct cgroup_subsys_state *css,
@@ -331,7 +332,7 @@ static void __init __hugetlb_cgroup_file_init(int idx)snprintf (cft->name,MAX_CFTYPE_NAME ,"%s.limit_in_bytes" , buf); cft->private =MEMFILE_PRIVATE (idx,RES_LIMIT ); cft->read_u64 = hugetlb_cgroup_read_u64; - cft->write_string = hugetlb_cgroup_write; + cft->write = hugetlb_cgroup_write;/* Add the usage file */ cft = &h->cgroup_files[1 ];
mm/memcontrol.c +25 -21
135 lines not on this page · raw message
net/core/netprio_cgroup.c +6 -6
@@ -185,15 +185,15 @@ static int read_priomap(struct seq_file *sf, void *v)return 0 ; } -static int write_priomap (struct cgroup_subsys_state *css,struct cftype *cft, -char *buffer) +static ssize_t write_priomap (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {char devname[IFNAMSIZ +1 ];struct net_device *dev;u32 prio;int ret; - if (sscanf(buffer, "%"__stringify(IFNAMSIZ)"s %u", devname, &prio) != 2) + if (sscanf(buf, "%"__stringify(IFNAMSIZ)"s %u", devname, &prio) != 2)return -EINVAL ; dev =dev_get_by_name (&init_net, devname);
@@ -202,11 +202,11 @@ static int write_priomap(struct cgroup_subsys_state *css, struct cftype *cft,rtnl_lock (); - ret =netprio_set_prio (css, dev, prio); + ret =netprio_set_prio (of_css (of), dev, prio);rtnl_unlock ();dev_put (dev); -return ret; +return ret ?: nbytes; }static int update_netprio (const void *v,struct file *file,unsigned n)
@@ -239,7 +239,7 @@ static struct cftype ss_files[] = { { .name = "ifpriomap", .seq_show = read_priomap, - .write_string = write_priomap, + .write = write_priomap, }, { }/* terminate */ };
net/ipv4/tcp_memcontrol.c +9 -7
@@ -102,17 +102,19 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)return 0 ; } -static int tcp_cgroup_write (struct cgroup_subsys_state *css,struct cftype *cft, -char *buffer) +static ssize_t tcp_cgroup_write (struct kernfs_open_file *of, +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));unsigned long long val;int ret =0 ; -switch (cft->private) { + buf =strstrip (buf); + +switch (of_cft (of)->private) {case RES_LIMIT :/* see memcontrol.c */ - ret =res_counter_memparse_write_strategy (buffer, &val); + ret =res_counter_memparse_write_strategy (buf, &val);if (ret)break ; ret =tcp_update_limit (memcg, val);
@@ -121,7 +123,7 @@ static int tcp_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, ret = -EINVAL ;break ; } -return ret; +return ret ?: nbytes; }static u64 tcp_read_stat (struct mem_cgroup *memcg,int type,u64 default_val)
@@ -193,7 +195,7 @@ static int tcp_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event)static struct cftype tcp_files[] = { { .name ="kmem.tcp.limit_in_bytes" , - .write_string = tcp_cgroup_write, + .write = tcp_cgroup_write, .read_u64 = tcp_cgroup_read, .private =RES_LIMIT , },
security/device_cgroup.c +7 -7
@@ -651,27 +651,27 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,return rc; } -static int devcgroup_access_write (struct cgroup_subsys_state *css, -struct cftype *cft,char *buffer) +static ssize_t devcgroup_access_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int retval;mutex_lock (&devcgroup_mutex); - retval =devcgroup_update_access (css_to_devcgroup (css), - cft->private, buffer); + retval =devcgroup_update_access (css_to_devcgroup (of_css (of)), +of_cft (of)->private,strstrip (buf));mutex_unlock (&devcgroup_mutex); -return retval; +return retval ?: nbytes; }static struct cftype dev_cgroup_files[] = { { .name ="allow" , - .write_string = devcgroup_access_write, + .write = devcgroup_access_write, .private =DEVCG_ALLOW , }, { .name ="deny" , - .write_string = devcgroup_access_write, + .write = devcgroup_access_write, .private =DEVCG_DENY , }, {
Signature · 1 line
1.9.0
Re: [PATCH 2/5] cgroup: replace cftype->write_string() with cftype->write()
In reply to Tejun HeoQuoted 29 lines · Tejun Heo
Convert all
cftype->write_string()users to the newcftype->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()andof_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 doesn't need this as
blkg_conf_prep()can 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 aboutCGROUP_LOCAL_BUFFER_SIZEincgroup_freezer.c.This patch doesn't introduce any visible behavior changes.
Signed-off-by Tejun Heo <[email protected]>Cc Vivek Goyal <[email protected]>Cc Jens Axboe <axboe-tSWWG44O7X1aa/[email protected]>Cc Li Zefan <[email protected]>Cc Johannes Weiner <[email protected]>Cc Michal Hocko <[email protected]>Cc Aristeu Rozanski <[email protected]>
Quoted 3 lines
--- block/blk-throttle.c | 32 ++++++++++++++++---------------- block/cfq-iosched.c | 28 ++++++++++++++--------------
Ack to blk-throttle.c and cfq-iosched.c changes.
thanks
Vivek
Tejun Heo
maintainerPATCH 3/5 cgroup: replace cftype->trigger() with cftype->write()
In reply to Tejun Heocftype->trigger() is pointless. It's trivial to ignore the input buffer from a regular ->write() operation. Convert all ->trigger() users to ->write() and remove ->trigger().
This patch doesn't introduce any visible behavior changes.
--- include/linux/cgroup.h | 8 -------- kernel/cgroup.c | 5 +---- mm/hugetlb_cgroup.c | 16 ++++++++-------- mm/memcontrol.c | 34 ++++++++++++++++++---------------- net/ipv4/tcp_memcontrol.c | 15 ++++++++------- 5 files changed, 35 insertions(+), 43 deletions(-)
include/linux/cgroup.h +0 -8
@@ -502,14 +502,6 @@ struct cftype { s64 val);/* -* trigger() callback can be used to get some kick from the -* userspace, when the actual string written is not important -* at all. The private field can be used to determine the -* kick type for multiplexing. -*/ -int (*trigger)(struct cgroup_subsys_state *css,unsigned int event); - -/* * write() is the generic write callback which maps directly to * kernfs write operation and overrides all other operations. * Maximum write size is determined by ->max_write_len. Use
kernel/cgroup.c +1 -4
@@ -1034,8 +1034,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft)if (cft->read_u64 || cft->read_s64 || cft->seq_show) mode |=S_IRUGO ; -if (cft->write_u64 || cft->write_s64 || cft->write || - cft->trigger) +if (cft->write_u64 || cft->write_s64 || cft->write) mode |=S_IWUSR ;return mode;
@@ -2748,8 +2747,6 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, ret =kstrtoll (buf,0 , &v);if (!ret) ret = cft->write_s64 (css, cft, v); - }else if (cft->trigger) { - ret = cft->trigger (css, (unsigned int )cft->private); }else { ret = -EINVAL ; }
mm/hugetlb_cgroup.c +8 -8
@@ -284,14 +284,14 @@ static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of,return ret ?: nbytes; } -static int hugetlb_cgroup_reset (struct cgroup_subsys_state *css, -unsigned int event) +static ssize_t hugetlb_cgroup_reset (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {int idx, name, ret =0 ; -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 (event); - name =MEMFILE_ATTR (event); + idx =MEMFILE_IDX (of_cft (of)->private); + name =MEMFILE_ATTR (of_cft (of)->private);switch (name) {case RES_MAX_USAGE :
@@ -304,7 +304,7 @@ static int hugetlb_cgroup_reset(struct cgroup_subsys_state *css, ret = -EINVAL ;break ; } -return ret; +return ret ?: nbytes; }static char *mem_fmt (char *buf,int size,unsigned long hsize)
@@ -344,14 +344,14 @@ static void __init __hugetlb_cgroup_file_init(int idx) cft = &h->cgroup_files[2 ];snprintf (cft->name,MAX_CFTYPE_NAME ,"%s.max_usage_in_bytes" , buf); cft->private =MEMFILE_PRIVATE (idx,RES_MAX_USAGE ); - cft->trigger = hugetlb_cgroup_reset; + cft->write = hugetlb_cgroup_reset; cft->read_u64 = hugetlb_cgroup_read_u64;/* Add the failcntfile */ cft = &h->cgroup_files[3 ];snprintf (cft->name,MAX_CFTYPE_NAME ,"%s.failcnt" , buf); cft->private =MEMFILE_PRIVATE (idx,RES_FAILCNT ); - cft->trigger = hugetlb_cgroup_reset; + cft->write = hugetlb_cgroup_reset; cft->read_u64 = hugetlb_cgroup_read_u64;/* NULL terminate the last cft */
mm/memcontrol.c +18 -16
@@ -4885,14 +4885,15 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)return 0 ; } -static int mem_cgroup_force_empty_write (struct cgroup_subsys_state *css, -unsigned int event) +static ssize_t mem_cgroup_force_empty_write (struct kernfs_open_file *of, +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));if (mem_cgroup_is_root (memcg))return -EINVAL ; -return mem_cgroup_force_empty (memcg); +return mem_cgroup_force_empty (memcg) ?: nbytes; } static u64 mem_cgroup_hierarchy_read(struct cgroup_subsys_state *css,
@@ -5218,14 +5219,15 @@ out: *memsw_limit = min_memsw_limit; } -static int mem_cgroup_reset (struct cgroup_subsys_state *css,unsigned int event) +static ssize_t mem_cgroup_reset (struct kernfs_open_file *of,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));int name;enum res_type type; - type =MEMFILE_TYPE (event); - name =MEMFILE_ATTR (event); + type =MEMFILE_TYPE (of_cft (of)->private); + name =MEMFILE_ATTR (of_cft (of)->private);switch (name) {case RES_MAX_USAGE :
@@ -5250,7 +5252,7 @@ static int mem_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event)break ; } -return 0 ; +return nbytes; } static u64 mem_cgroup_move_charge_read(struct cgroup_subsys_state *css,
@@ -6103,7 +6105,7 @@ static struct cftype mem_cgroup_files[] = { { .name = "max_usage_in_bytes", .private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, {
@@ -6121,7 +6123,7 @@ static struct cftype mem_cgroup_files[] = { { .name = "failcnt", .private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, {
@@ -6130,7 +6132,7 @@ static struct cftype mem_cgroup_files[] = { }, { .name = "force_empty", - .trigger = mem_cgroup_force_empty_write, + .write = mem_cgroup_force_empty_write, }, { .name = "use_hierarchy",
@@ -6184,13 +6186,13 @@ static struct cftype mem_cgroup_files[] = { { .name = "kmem.failcnt", .private = MEMFILE_PRIVATE(_KMEM, RES_FAILCNT), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, { .name = "kmem.max_usage_in_bytes", .private = MEMFILE_PRIVATE(_KMEM, RES_MAX_USAGE), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, #ifdef CONFIG_SLABINFO
@@ -6213,7 +6215,7 @@ static struct cftype memsw_cgroup_files[] = { { .name = "memsw.max_usage_in_bytes", .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, {
@@ -6225,7 +6227,7 @@ static struct cftype memsw_cgroup_files[] = { { .name = "memsw.failcnt", .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT), - .trigger = mem_cgroup_reset, + .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, { }, /* terminate */
net/ipv4/tcp_memcontrol.c +8 -7
@@ -170,17 +170,18 @@ static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft)return val; } -static int tcp_cgroup_reset (struct cgroup_subsys_state *css,unsigned int event) +static ssize_t tcp_cgroup_reset (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) {struct mem_cgroup *memcg;struct cg_proto *cg_proto; - memcg =mem_cgroup_from_css (css); + memcg =mem_cgroup_from_css (of_css (of)); cg_proto = tcp_prot.proto_cgroup (memcg);if (!cg_proto) -return 0 ; +return nbytes; -switch (event) { +switch (of_cft (of)->private) {case RES_MAX_USAGE :res_counter_reset_max (&cg_proto->memory_allocated);break ;
@@ -189,7 +190,7 @@ static int tcp_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event)break ; } -return 0 ; +return nbytes; }static struct cftype tcp_files[] = {
@@ -207,13 +208,13 @@ static struct cftype tcp_files[] = { { .name = "kmem.tcp.failcnt", .private = RES_FAILCNT, - .trigger = tcp_cgroup_reset, + .write = tcp_cgroup_reset, .read_u64 = tcp_cgroup_read, }, { .name = "kmem.tcp.max_usage_in_bytes", .private = RES_MAX_USAGE, - .trigger = tcp_cgroup_reset, + .write = tcp_cgroup_reset, .read_u64 = tcp_cgroup_read, }, { } /* terminate */
Signature · 1 line
1.9.0
Tejun Heo
maintainerPATCH 4/5 cgroup: convert "tasks" and "cgroup.procs" handle to use cftype->write()
In reply to Tejun Heocgroup_tasks_write() and cgroup_procs_write() are currently using cftype->write_u64(). This patch converts them to use cftype->write() instead. This allows access to the associated kernfs_open_file which will be necessary to implement the planned kernfs active protection manipulation for these files.
This shifts buffer parsing to attach_task_by_pid() and makes it return @nbytes on success. Let's rename it to __cgroup_procs_write() to clearly indicate that this is a write handler implementation.
This patch doesn't introduce any visible behavior changes.
--- kernel/cgroup.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
kernel/cgroup.c +16 -10
@@ -2232,12 +2232,18 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,* function to attach either it or all tasks in its threadgroup. Will lock * cgroup_mutex and threadgroup. */ -static int attach_task_by_pid (struct cgroup *cgrp,u64 pid,bool threadgroup) +static ssize_t __cgroup_procs_write (struct kernfs_open_file *of,char *buf, +size_t nbytes,loff_t off,bool threadgroup) {struct task_struct *tsk;const struct cred *cred =current_cred (), *tcred; +struct cgroup *cgrp =of_css (of)->cgroup; +pid_t pid;int ret; +if (kstrtoint (strstrip (buf),0 , &pid) || pid <0 ) +return -EINVAL ; +if (!cgroup_lock_live_group (cgrp))return -ENODEV ;
@@ -2305,7 +2311,7 @@ retry_find_task:put_task_struct (tsk); out_unlock_cgroup:mutex_unlock (&cgroup_mutex); -return ret; +return ret ?: nbytes; }/**
@@ -2339,16 +2345,16 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk) }EXPORT_SYMBOL_GPL (cgroup_attach_task_all); -static int cgroup_tasks_write (struct cgroup_subsys_state *css, -struct cftype *cft,u64 pid) +static ssize_t cgroup_tasks_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) { -return attach_task_by_pid (css->cgroup, pid, false); +return __cgroup_procs_write (of, buf, nbytes, off, false); } -static int cgroup_procs_write (struct cgroup_subsys_state *css, -struct cftype *cft,u64 tgid) +static ssize_t cgroup_procs_write (struct kernfs_open_file *of, +char *buf,size_t nbytes,loff_t off) { -return attach_task_by_pid (css->cgroup, tgid, true); +return __cgroup_procs_write (of, buf, nbytes, off, true); } static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of,
@@ -3951,7 +3957,7 @@ static struct cftype cgroup_base_files[] = { .seq_stop = cgroup_pidlist_stop, .seq_show = cgroup_pidlist_show, .private = CGROUP_FILE_PROCS, - .write_u64 = cgroup_procs_write, + .write = cgroup_procs_write, .mode = S_IRUGO | S_IWUSR, }, {
@@ -4000,7 +4006,7 @@ static struct cftype cgroup_base_files[] = { .seq_stop = cgroup_pidlist_stop, .seq_show = cgroup_pidlist_show, .private = CGROUP_FILE_TASKS, - .write_u64 = cgroup_tasks_write, + .write = cgroup_tasks_write, .mode = S_IRUGO | S_IWUSR, }, {
Signature · 1 line
1.9.0
Tejun Heo
maintainerPATCH 5/5 cgroup: remove cgroup->control_kn
In reply to Tejun HeoNow that cgroup_subtree_control_write() has access to the associated kernfs_open_file and thus the kernfs_node, there's no need to cache it in cgroup->control_kn on creation. Remove cgroup->control_kn and use @of->kn directly.
--- include/linux/cgroup.h | 1 - kernel/cgroup.c | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-)
include/linux/cgroup.h +0 -1
@@ -179,7 +179,6 @@ struct cgroup {struct cgroup *parent;/* my parent */ struct kernfs_node *kn;/* cgroup kernfs entry */ -struct kernfs_node *control_kn;/* kn for "cgroup.subtree_control" */ struct kernfs_node *populated_kn;/* kn for "cgroup.subtree_populated" */ /*
kernel/cgroup.c +3 -5
@@ -2578,7 +2578,7 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,* active_ref protection. */ cgroup_get (cgrp); -kernfs_break_active_protection (cgrp->control_kn); +kernfs_break_active_protection (of->kn);mutex_lock (&cgroup_tree_mutex);
@@ -2695,7 +2695,7 @@ out_unlock: out_unlock_tree:mutex_unlock (&cgroup_tree_mutex); out_unbreak: -kernfs_unbreak_active_protection (cgrp->control_kn); +kernfs_unbreak_active_protection (of->kn);cgroup_put (cgrp);return ret ?: nbytes;
@@ -2885,9 +2885,7 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)return ret; } -if (cft->seq_show == cgroup_subtree_control_show) - cgrp->control_kn = kn; -else if (cft->seq_show == cgroup_populated_show) +if (cft->seq_show == cgroup_populated_show) cgrp->populated_kn = kn;return 0 ; }
Signature · 1 line
1.9.0
Tejun Heo
maintainerQuoted 8 lines · Tejun Heo
This patchset is on top of
cgroup/for-3.16
12d3089c192c("kernel/cpuset.c: convert printk topr_foo()")
+ [1] [PATCHSET cgroup/for-3.16] cgroup: post unified hierarchy fixes and updatesand available on the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.gitreview-post-unified-updates
Refreshed without content change on top of
b9a63d0116e8 ("Merge branch 'for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu into for-3.16")
+ [1] [PATCHSET v2 cgroup/for-3.16] cgroup: post unified hierarchy fixes and updates
and available on the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-post-unified-updates-v2
Signature · 3 lines
tejun [1] http://lkml.kernel.org/g/1399663975-315-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Quoted 41 lines · Tejun Heo
Hello,
This patchset implements a new cftype operation ->write() and replace ->write_string() and ->trigger() with it. ->write() is similar to ->write_string() but maps directly to the kernfs write operation and has access to all available context information including the associated
kernfs_open_file, which will make things like implementing kernfs active protection manipulation easier.->write_string() becomes redundant and ->trigger() has always been spurious. This patch replaces all users of the two methods to ->write() and remove them.
This patchset contains the following five patches.
0001-cgroup-implement-cftype-write.patch 0002-cgroup-replace-cftype-write_string-with-cftype-write.patch 0003-cgroup-replace-cftype-trigger-with-cftype-write.patch 0004-cgroup-convert-tasks-and-cgroup.procs-handle-to-use-.patch 0005-cgroup-remove-cgroup-control_kn.patch
0001 implements
cftype->write().0002-0003 replace
cftype->write_string()and ->trigger() with it.0004 convert "tasks" and "cgroup.procs" handler too.
0005 removes
cgroup->control_knas thekernfs_nodeis now directly accessible fromkernfs_open_file.This patchset is on top of
cgroup/for-3.16
12d3089c192c("kernel/cpuset.c: convert printk topr_foo()")
+ [1] [PATCHSET cgroup/for-3.16] cgroup: post unified hierarchy fixes and updatesand available on the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.gitreview-post-unified-updatesdiffstat follows.
Quoted 12 lines
block/blk-throttle.c | 32 ++++++++--------- block/cfq-iosched.c | 28 +++++++-------- include/linux/cgroup.h | 40 +++++++++++---------- kernel/cgroup.c | 85 +++++++++++++++++++++++----------------------- kernel/cgroup_freezer.c | 20 ++++------ kernel/cpuset.c | 16 ++++---- mm/hugetlb_cgroup.c | 33 +++++++++-------- mm/memcontrol.c | 80 +++++++++++++++++++++++-------------------- net/ipv4/tcp_memcontrol.c | 31 +++++++++------- security/device_cgroup.c | 14 +++---- 10 files changed, 197 insertions(+), 182 deletions(-)
Quoted 13 lines · Tejun Heo
Hello,
This patchset implements a new cftype operation ->write() and replace ->write_string() and ->trigger() with it. ->write() is similar to ->write_string() but maps directly to the kernfs write operation and has access to all available context information including the associated
kernfs_open_file, which will make things like implementing kernfs active protection manipulation easier.->write_string() becomes redundant and ->trigger() has always been spurious. This patch replaces all users of the two methods to ->write() and remove them.
Quoted 7 lines
This patchset contains the following five patches.
0001-cgroup-implement-cftype-write.patch 0002-cgroup-replace-cftype-write_string-with-cftype-write.patch 0003-cgroup-replace-cftype-trigger-with-cftype-write.patch 0004-cgroup-convert-tasks-and-cgroup.procs-handle-to-use-.patch 0005-cgroup-remove-cgroup-control_kn.patch
Applied to cgroup/for-3.16.
Thanks.
Signature · 1 line
tejun