Commit b4168640 authored by Tejun Heo's avatar Tejun Heo

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.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
parent ec903c0c
...@@ -515,6 +515,15 @@ struct cftype { ...@@ -515,6 +515,15 @@ struct cftype {
*/ */
int (*trigger)(struct cgroup_subsys_state *css, unsigned int event); 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 #ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lock_class_key lockdep_key; struct lock_class_key lockdep_key;
#endif #endif
...@@ -552,14 +561,24 @@ static inline ino_t cgroup_ino(struct cgroup *cgrp) ...@@ -552,14 +561,24 @@ static inline ino_t cgroup_ino(struct cgroup *cgrp)
return 0; 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; 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 * Name / path handling functions. All are thin wrappers around the kernfs
......
...@@ -283,11 +283,10 @@ static inline bool cgroup_is_dead(const struct cgroup *cgrp) ...@@ -283,11 +283,10 @@ static inline bool cgroup_is_dead(const struct cgroup *cgrp)
return test_bit(CGRP_DEAD, &cgrp->flags); 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 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(). * This is open and unprotected implementation of cgroup_css().
...@@ -302,7 +301,7 @@ struct cgroup_subsys_state *seq_css(struct seq_file *seq) ...@@ -302,7 +301,7 @@ struct cgroup_subsys_state *seq_css(struct seq_file *seq)
else else
return &cgrp->dummy_css; return &cgrp->dummy_css;
} }
EXPORT_SYMBOL_GPL(seq_css); EXPORT_SYMBOL_GPL(of_css);
/** /**
* cgroup_is_descendant - test ancestry * cgroup_is_descendant - test ancestry
...@@ -1035,8 +1034,8 @@ static umode_t cgroup_file_mode(const struct cftype *cft) ...@@ -1035,8 +1034,8 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
if (cft->read_u64 || cft->read_s64 || cft->seq_show) if (cft->read_u64 || cft->read_s64 || cft->seq_show)
mode |= S_IRUGO; mode |= S_IRUGO;
if (cft->write_u64 || cft->write_s64 || cft->write_string || if (cft->write_u64 || cft->write_s64 || cft->write ||
cft->trigger) cft->write_string || cft->trigger)
mode |= S_IWUSR; mode |= S_IWUSR;
return mode; return mode;
...@@ -2726,6 +2725,9 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, ...@@ -2726,6 +2725,9 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
struct cgroup_subsys_state *css; struct cgroup_subsys_state *css;
int ret; int ret;
if (cft->write)
return cft->write(of, buf, nbytes, off);
/* /*
* kernfs guarantees that a file isn't deleted with operations in * kernfs guarantees that a file isn't deleted with operations in
* flight, which means that the matching css is and stays alive and * flight, which means that the matching css is and stays alive and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment