]> git.baikalelectronics.ru Git - kernel.git/commitdiff
cgroup: Allocate cgroup_file_ctx for kernfs_open_file->priv
authorTejun Heo <tj@kernel.org>
Thu, 6 Jan 2022 21:02:29 +0000 (11:02 -1000)
committerTejun Heo <tj@kernel.org>
Thu, 6 Jan 2022 21:02:29 +0000 (11:02 -1000)
of->priv is currently used by each interface file implementation to store
private information. This patch collects the current two private data usages
into struct cgroup_file_ctx which is allocated and freed by the common path.
This allows generic private data which applies to multiple files, which will
be used to in the following patch.

Note that cgroup_procs iterator is now embedded as procs.iter in the new
cgroup_file_ctx so that it doesn't need to be allocated and freed
separately.

v2: union dropped from cgroup_file_ctx and the procs iterator is embedded in
    cgroup_file_ctx as suggested by Linus.

v3: Michal pointed out that cgroup1's procs pidlist uses of->priv too.
    Converted. Didn't change to embedded allocation as cgroup1 pidlists get
    stored for caching.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Michal Koutný <mkoutny@suse.com>
kernel/cgroup/cgroup-internal.h
kernel/cgroup/cgroup-v1.c
kernel/cgroup/cgroup.c

index bfbeabc17a9dfd84ddf724a657687f5c548fa1f4..cf637bc4ab45374bebc3ef7b28421f38257d9312 100644 (file)
@@ -65,6 +65,23 @@ static inline struct cgroup_fs_context *cgroup_fc2context(struct fs_context *fc)
        return container_of(kfc, struct cgroup_fs_context, kfc);
 }
 
+struct cgroup_pidlist;
+
+struct cgroup_file_ctx {
+       struct {
+               void                    *trigger;
+       } psi;
+
+       struct {
+               bool                    started;
+               struct css_task_iter    iter;
+       } procs;
+
+       struct {
+               struct cgroup_pidlist   *pidlist;
+       } procs1;
+};
+
 /*
  * A cgroup can be associated with multiple css_sets as different tasks may
  * belong to different cgroups on different hierarchies.  In the other
index 0e7369103ba615394214f10403e823747076045d..41e0837a5a0bda17b361b87f4a4faf4790eb0b8a 100644 (file)
@@ -394,6 +394,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
         * next pid to display, if any
         */
        struct kernfs_open_file *of = s->private;
+       struct cgroup_file_ctx *ctx = of->priv;
        struct cgroup *cgrp = seq_css(s)->cgroup;
        struct cgroup_pidlist *l;
        enum cgroup_filetype type = seq_cft(s)->private;
@@ -403,25 +404,24 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
        mutex_lock(&cgrp->pidlist_mutex);
 
        /*
-        * !NULL @of->priv indicates that this isn't the first start()
-        * after open.  If the matching pidlist is around, we can use that.
-        * Look for it.  Note that @of->priv can't be used directly.  It
-        * could already have been destroyed.
+        * !NULL @ctx->procs1.pidlist indicates that this isn't the first
+        * start() after open. If the matching pidlist is around, we can use
+        * that. Look for it. Note that @ctx->procs1.pidlist can't be used
+        * directly. It could already have been destroyed.
         */
-       if (of->priv)
-               of->priv = cgroup_pidlist_find(cgrp, type);
+       if (ctx->procs1.pidlist)
+               ctx->procs1.pidlist = cgroup_pidlist_find(cgrp, type);
 
        /*
         * Either this is the first start() after open or the matching
         * pidlist has been destroyed inbetween.  Create a new one.
         */
-       if (!of->priv) {
-               ret = pidlist_array_load(cgrp, type,
-                                        (struct cgroup_pidlist **)&of->priv);
+       if (!ctx->procs1.pidlist) {
+               ret = pidlist_array_load(cgrp, type, &ctx->procs1.pidlist);
                if (ret)
                        return ERR_PTR(ret);
        }
-       l = of->priv;
+       l = ctx->procs1.pidlist;
 
        if (pid) {
                int end = l->length;
@@ -449,7 +449,8 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
 static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 {
        struct kernfs_open_file *of = s->private;
-       struct cgroup_pidlist *l = of->priv;
+       struct cgroup_file_ctx *ctx = of->priv;
+       struct cgroup_pidlist *l = ctx->procs1.pidlist;
 
        if (l)
                mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork,
@@ -460,7 +461,8 @@ static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
 {
        struct kernfs_open_file *of = s->private;
-       struct cgroup_pidlist *l = of->priv;
+       struct cgroup_file_ctx *ctx = of->priv;
+       struct cgroup_pidlist *l = ctx->procs1.pidlist;
        pid_t *p = v;
        pid_t *end = l->list + l->length;
        /*
index 2632e46da1d4a0f81a14948137c109b959603847..a84631d08d98cd508c078caad9ae0adf51b87c27 100644 (file)
@@ -3630,6 +3630,7 @@ static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
 static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
                                          size_t nbytes, enum psi_res res)
 {
+       struct cgroup_file_ctx *ctx = of->priv;
        struct psi_trigger *new;
        struct cgroup *cgrp;
        struct psi_group *psi;
@@ -3648,7 +3649,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
                return PTR_ERR(new);
        }
 
-       psi_trigger_replace(&of->priv, new);
+       psi_trigger_replace(&ctx->psi.trigger, new);
 
        cgroup_put(cgrp);
 
@@ -3679,12 +3680,16 @@ static ssize_t cgroup_cpu_pressure_write(struct kernfs_open_file *of,
 static __poll_t cgroup_pressure_poll(struct kernfs_open_file *of,
                                          poll_table *pt)
 {
-       return psi_trigger_poll(&of->priv, of->file, pt);
+       struct cgroup_file_ctx *ctx = of->priv;
+
+       return psi_trigger_poll(&ctx->psi.trigger, of->file, pt);
 }
 
 static void cgroup_pressure_release(struct kernfs_open_file *of)
 {
-       psi_trigger_replace(&of->priv, NULL);
+       struct cgroup_file_ctx *ctx = of->priv;
+
+       psi_trigger_replace(&ctx->psi.trigger, NULL);
 }
 
 bool cgroup_psi_enabled(void)
@@ -3811,18 +3816,31 @@ static ssize_t cgroup_kill_write(struct kernfs_open_file *of, char *buf,
 static int cgroup_file_open(struct kernfs_open_file *of)
 {
        struct cftype *cft = of_cft(of);
+       struct cgroup_file_ctx *ctx;
+       int ret;
 
-       if (cft->open)
-               return cft->open(of);
-       return 0;
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       of->priv = ctx;
+
+       if (!cft->open)
+               return 0;
+
+       ret = cft->open(of);
+       if (ret)
+               kfree(ctx);
+       return ret;
 }
 
 static void cgroup_file_release(struct kernfs_open_file *of)
 {
        struct cftype *cft = of_cft(of);
+       struct cgroup_file_ctx *ctx = of->priv;
 
        if (cft->release)
                cft->release(of);
+       kfree(ctx);
 }
 
 static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
@@ -4751,21 +4769,21 @@ void css_task_iter_end(struct css_task_iter *it)
 
 static void cgroup_procs_release(struct kernfs_open_file *of)
 {
-       if (of->priv) {
-               css_task_iter_end(of->priv);
-               kfree(of->priv);
-       }
+       struct cgroup_file_ctx *ctx = of->priv;
+
+       if (ctx->procs.started)
+               css_task_iter_end(&ctx->procs.iter);
 }
 
 static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos)
 {
        struct kernfs_open_file *of = s->private;
-       struct css_task_iter *it = of->priv;
+       struct cgroup_file_ctx *ctx = of->priv;
 
        if (pos)
                (*pos)++;
 
-       return css_task_iter_next(it);
+       return css_task_iter_next(&ctx->procs.iter);
 }
 
 static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
@@ -4773,21 +4791,18 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
 {
        struct kernfs_open_file *of = s->private;
        struct cgroup *cgrp = seq_css(s)->cgroup;
-       struct css_task_iter *it = of->priv;
+       struct cgroup_file_ctx *ctx = of->priv;
+       struct css_task_iter *it = &ctx->procs.iter;
 
        /*
         * When a seq_file is seeked, it's always traversed sequentially
         * from position 0, so we can simply keep iterating on !0 *pos.
         */
-       if (!it) {
+       if (!ctx->procs.started) {
                if (WARN_ON_ONCE((*pos)))
                        return ERR_PTR(-EINVAL);
-
-               it = kzalloc(sizeof(*it), GFP_KERNEL);
-               if (!it)
-                       return ERR_PTR(-ENOMEM);
-               of->priv = it;
                css_task_iter_start(&cgrp->self, iter_flags, it);
+               ctx->procs.started = true;
        } else if (!(*pos)) {
                css_task_iter_end(it);
                css_task_iter_start(&cgrp->self, iter_flags, it);