linux/net/core/netclassid_cgroup.c
<<
>>
Prefs
   1/*
   2 * net/core/netclassid_cgroup.c Classid Cgroupfs Handling
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Thomas Graf <tgraf@suug.ch>
  10 */
  11
  12#include <linux/slab.h>
  13#include <linux/cgroup.h>
  14#include <linux/fdtable.h>
  15#include <linux/sched/task.h>
  16
  17#include <net/cls_cgroup.h>
  18#include <net/sock.h>
  19
  20static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css)
  21{
  22        return css ? container_of(css, struct cgroup_cls_state, css) : NULL;
  23}
  24
  25struct cgroup_cls_state *task_cls_state(struct task_struct *p)
  26{
  27        return css_cls_state(task_css_check(p, net_cls_cgrp_id,
  28                                            rcu_read_lock_bh_held()));
  29}
  30EXPORT_SYMBOL_GPL(task_cls_state);
  31
  32static struct cgroup_subsys_state *
  33cgrp_css_alloc(struct cgroup_subsys_state *parent_css)
  34{
  35        struct cgroup_cls_state *cs;
  36
  37        cs = kzalloc(sizeof(*cs), GFP_KERNEL);
  38        if (!cs)
  39                return ERR_PTR(-ENOMEM);
  40
  41        return &cs->css;
  42}
  43
  44static int cgrp_css_online(struct cgroup_subsys_state *css)
  45{
  46        struct cgroup_cls_state *cs = css_cls_state(css);
  47        struct cgroup_cls_state *parent = css_cls_state(css->parent);
  48
  49        if (parent)
  50                cs->classid = parent->classid;
  51
  52        return 0;
  53}
  54
  55static void cgrp_css_free(struct cgroup_subsys_state *css)
  56{
  57        kfree(css_cls_state(css));
  58}
  59
  60static int update_classid_sock(const void *v, struct file *file, unsigned n)
  61{
  62        int err;
  63        struct socket *sock = sock_from_file(file, &err);
  64
  65        if (sock) {
  66                spin_lock(&cgroup_sk_update_lock);
  67                sock_cgroup_set_classid(&sock->sk->sk_cgrp_data,
  68                                        (unsigned long)v);
  69                spin_unlock(&cgroup_sk_update_lock);
  70        }
  71        return 0;
  72}
  73
  74static void cgrp_attach(struct cgroup_taskset *tset)
  75{
  76        struct cgroup_subsys_state *css;
  77        struct task_struct *p;
  78
  79        cgroup_taskset_for_each(p, css, tset) {
  80                task_lock(p);
  81                iterate_fd(p->files, 0, update_classid_sock,
  82                           (void *)(unsigned long)css_cls_state(css)->classid);
  83                task_unlock(p);
  84        }
  85}
  86
  87static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft)
  88{
  89        return css_cls_state(css)->classid;
  90}
  91
  92static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
  93                         u64 value)
  94{
  95        struct cgroup_cls_state *cs = css_cls_state(css);
  96        struct css_task_iter it;
  97        struct task_struct *p;
  98
  99        cgroup_sk_alloc_disable();
 100
 101        cs->classid = (u32)value;
 102
 103        css_task_iter_start(css, 0, &it);
 104        while ((p = css_task_iter_next(&it))) {
 105                task_lock(p);
 106                iterate_fd(p->files, 0, update_classid_sock,
 107                           (void *)(unsigned long)cs->classid);
 108                task_unlock(p);
 109                cond_resched();
 110        }
 111        css_task_iter_end(&it);
 112
 113        return 0;
 114}
 115
 116static struct cftype ss_files[] = {
 117        {
 118                .name           = "classid",
 119                .read_u64       = read_classid,
 120                .write_u64      = write_classid,
 121        },
 122        { }     /* terminate */
 123};
 124
 125struct cgroup_subsys net_cls_cgrp_subsys = {
 126        .css_alloc              = cgrp_css_alloc,
 127        .css_online             = cgrp_css_online,
 128        .css_free               = cgrp_css_free,
 129        .attach                 = cgrp_attach,
 130        .legacy_cftypes         = ss_files,
 131};
 132