diff options
-rw-r--r-- | include/net/netprio_cgroup.h | 11 | ||||
-rw-r--r-- | net/core/netprio_cgroup.c | 65 |
2 files changed, 15 insertions, 61 deletions
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h index 2760f4f4ae9b..1d04b6f0fbd4 100644 --- a/include/net/netprio_cgroup.h +++ b/include/net/netprio_cgroup.h | |||
@@ -27,7 +27,6 @@ struct netprio_map { | |||
27 | 27 | ||
28 | struct cgroup_netprio_state { | 28 | struct cgroup_netprio_state { |
29 | struct cgroup_subsys_state css; | 29 | struct cgroup_subsys_state css; |
30 | u32 prioidx; | ||
31 | }; | 30 | }; |
32 | 31 | ||
33 | extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); | 32 | extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); |
@@ -36,13 +35,12 @@ extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); | |||
36 | 35 | ||
37 | static inline u32 task_netprioidx(struct task_struct *p) | 36 | static inline u32 task_netprioidx(struct task_struct *p) |
38 | { | 37 | { |
39 | struct cgroup_netprio_state *state; | 38 | struct cgroup_subsys_state *css; |
40 | u32 idx; | 39 | u32 idx; |
41 | 40 | ||
42 | rcu_read_lock(); | 41 | rcu_read_lock(); |
43 | state = container_of(task_subsys_state(p, net_prio_subsys_id), | 42 | css = task_subsys_state(p, net_prio_subsys_id); |
44 | struct cgroup_netprio_state, css); | 43 | idx = css->cgroup->id; |
45 | idx = state->prioidx; | ||
46 | rcu_read_unlock(); | 44 | rcu_read_unlock(); |
47 | return idx; | 45 | return idx; |
48 | } | 46 | } |
@@ -57,8 +55,7 @@ static inline u32 task_netprioidx(struct task_struct *p) | |||
57 | rcu_read_lock(); | 55 | rcu_read_lock(); |
58 | css = task_subsys_state(p, net_prio_subsys_id); | 56 | css = task_subsys_state(p, net_prio_subsys_id); |
59 | if (css) | 57 | if (css) |
60 | idx = container_of(css, | 58 | idx = css->cgroup->id; |
61 | struct cgroup_netprio_state, css)->prioidx; | ||
62 | rcu_read_unlock(); | 59 | rcu_read_unlock(); |
63 | return idx; | 60 | return idx; |
64 | } | 61 | } |
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 569d83da53d0..9409cdf9f268 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
@@ -28,10 +28,6 @@ | |||
28 | #include <linux/fdtable.h> | 28 | #include <linux/fdtable.h> |
29 | 29 | ||
30 | #define PRIOMAP_MIN_SZ 128 | 30 | #define PRIOMAP_MIN_SZ 128 |
31 | #define PRIOIDX_SZ 128 | ||
32 | |||
33 | static unsigned long prioidx_map[PRIOIDX_SZ]; | ||
34 | static DEFINE_SPINLOCK(prioidx_map_lock); | ||
35 | 31 | ||
36 | static inline struct cgroup_netprio_state *cgrp_netprio_state(struct cgroup *cgrp) | 32 | static inline struct cgroup_netprio_state *cgrp_netprio_state(struct cgroup *cgrp) |
37 | { | 33 | { |
@@ -39,32 +35,6 @@ static inline struct cgroup_netprio_state *cgrp_netprio_state(struct cgroup *cgr | |||
39 | struct cgroup_netprio_state, css); | 35 | struct cgroup_netprio_state, css); |
40 | } | 36 | } |
41 | 37 | ||
42 | static int get_prioidx(u32 *prio) | ||
43 | { | ||
44 | unsigned long flags; | ||
45 | u32 prioidx; | ||
46 | |||
47 | spin_lock_irqsave(&prioidx_map_lock, flags); | ||
48 | prioidx = find_first_zero_bit(prioidx_map, sizeof(unsigned long) * PRIOIDX_SZ); | ||
49 | if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ) { | ||
50 | spin_unlock_irqrestore(&prioidx_map_lock, flags); | ||
51 | return -ENOSPC; | ||
52 | } | ||
53 | set_bit(prioidx, prioidx_map); | ||
54 | spin_unlock_irqrestore(&prioidx_map_lock, flags); | ||
55 | *prio = prioidx; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static void put_prioidx(u32 idx) | ||
60 | { | ||
61 | unsigned long flags; | ||
62 | |||
63 | spin_lock_irqsave(&prioidx_map_lock, flags); | ||
64 | clear_bit(idx, prioidx_map); | ||
65 | spin_unlock_irqrestore(&prioidx_map_lock, flags); | ||
66 | } | ||
67 | |||
68 | /* | 38 | /* |
69 | * Extend @dev->priomap so that it's large enough to accomodate | 39 | * Extend @dev->priomap so that it's large enough to accomodate |
70 | * @target_idx. @dev->priomap.priomap_len > @target_idx after successful | 40 | * @target_idx. @dev->priomap.priomap_len > @target_idx after successful |
@@ -120,62 +90,50 @@ static int extend_netdev_table(struct net_device *dev, u32 target_idx) | |||
120 | static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp) | 90 | static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp) |
121 | { | 91 | { |
122 | struct cgroup_netprio_state *cs; | 92 | struct cgroup_netprio_state *cs; |
123 | int ret = -EINVAL; | 93 | |
94 | if (cgrp->parent && cgrp->parent->id) | ||
95 | return ERR_PTR(-EINVAL); | ||
124 | 96 | ||
125 | cs = kzalloc(sizeof(*cs), GFP_KERNEL); | 97 | cs = kzalloc(sizeof(*cs), GFP_KERNEL); |
126 | if (!cs) | 98 | if (!cs) |
127 | return ERR_PTR(-ENOMEM); | 99 | return ERR_PTR(-ENOMEM); |
128 | 100 | ||
129 | if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) | ||
130 | goto out; | ||
131 | |||
132 | ret = get_prioidx(&cs->prioidx); | ||
133 | if (ret < 0) { | ||
134 | pr_warn("No space in priority index array\n"); | ||
135 | goto out; | ||
136 | } | ||
137 | |||
138 | return &cs->css; | 101 | return &cs->css; |
139 | out: | ||
140 | kfree(cs); | ||
141 | return ERR_PTR(ret); | ||
142 | } | 102 | } |
143 | 103 | ||
144 | static void cgrp_css_free(struct cgroup *cgrp) | 104 | static void cgrp_css_free(struct cgroup *cgrp) |
145 | { | 105 | { |
146 | struct cgroup_netprio_state *cs; | 106 | struct cgroup_netprio_state *cs = cgrp_netprio_state(cgrp); |
147 | struct net_device *dev; | 107 | struct net_device *dev; |
148 | struct netprio_map *map; | 108 | struct netprio_map *map; |
149 | 109 | ||
150 | cs = cgrp_netprio_state(cgrp); | ||
151 | rtnl_lock(); | 110 | rtnl_lock(); |
152 | for_each_netdev(&init_net, dev) { | 111 | for_each_netdev(&init_net, dev) { |
153 | map = rtnl_dereference(dev->priomap); | 112 | map = rtnl_dereference(dev->priomap); |
154 | if (map && cs->prioidx < map->priomap_len) | 113 | if (map && cgrp->id < map->priomap_len) |
155 | map->priomap[cs->prioidx] = 0; | 114 | map->priomap[cgrp->id] = 0; |
156 | } | 115 | } |
157 | rtnl_unlock(); | 116 | rtnl_unlock(); |
158 | put_prioidx(cs->prioidx); | ||
159 | kfree(cs); | 117 | kfree(cs); |
160 | } | 118 | } |
161 | 119 | ||
162 | static u64 read_prioidx(struct cgroup *cgrp, struct cftype *cft) | 120 | static u64 read_prioidx(struct cgroup *cgrp, struct cftype *cft) |
163 | { | 121 | { |
164 | return (u64)cgrp_netprio_state(cgrp)->prioidx; | 122 | return cgrp->id; |
165 | } | 123 | } |
166 | 124 | ||
167 | static int read_priomap(struct cgroup *cont, struct cftype *cft, | 125 | static int read_priomap(struct cgroup *cont, struct cftype *cft, |
168 | struct cgroup_map_cb *cb) | 126 | struct cgroup_map_cb *cb) |
169 | { | 127 | { |
170 | struct net_device *dev; | 128 | struct net_device *dev; |
171 | u32 prioidx = cgrp_netprio_state(cont)->prioidx; | 129 | u32 id = cont->id; |
172 | u32 priority; | 130 | u32 priority; |
173 | struct netprio_map *map; | 131 | struct netprio_map *map; |
174 | 132 | ||
175 | rcu_read_lock(); | 133 | rcu_read_lock(); |
176 | for_each_netdev_rcu(&init_net, dev) { | 134 | for_each_netdev_rcu(&init_net, dev) { |
177 | map = rcu_dereference(dev->priomap); | 135 | map = rcu_dereference(dev->priomap); |
178 | priority = (map && prioidx < map->priomap_len) ? map->priomap[prioidx] : 0; | 136 | priority = (map && id < map->priomap_len) ? map->priomap[id] : 0; |
179 | cb->fill(cb, dev->name, priority); | 137 | cb->fill(cb, dev->name, priority); |
180 | } | 138 | } |
181 | rcu_read_unlock(); | 139 | rcu_read_unlock(); |
@@ -185,7 +143,6 @@ static int read_priomap(struct cgroup *cont, struct cftype *cft, | |||
185 | static int write_priomap(struct cgroup *cgrp, struct cftype *cft, | 143 | static int write_priomap(struct cgroup *cgrp, struct cftype *cft, |
186 | const char *buffer) | 144 | const char *buffer) |
187 | { | 145 | { |
188 | u32 prioidx = cgrp_netprio_state(cgrp)->prioidx; | ||
189 | char devname[IFNAMSIZ + 1]; | 146 | char devname[IFNAMSIZ + 1]; |
190 | struct net_device *dev; | 147 | struct net_device *dev; |
191 | struct netprio_map *map; | 148 | struct netprio_map *map; |
@@ -201,13 +158,13 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, | |||
201 | 158 | ||
202 | rtnl_lock(); | 159 | rtnl_lock(); |
203 | 160 | ||
204 | ret = extend_netdev_table(dev, prioidx); | 161 | ret = extend_netdev_table(dev, cgrp->id); |
205 | if (ret) | 162 | if (ret) |
206 | goto out_unlock; | 163 | goto out_unlock; |
207 | 164 | ||
208 | map = rtnl_dereference(dev->priomap); | 165 | map = rtnl_dereference(dev->priomap); |
209 | if (map) | 166 | if (map) |
210 | map->priomap[prioidx] = prio; | 167 | map->priomap[cgrp->id] = prio; |
211 | out_unlock: | 168 | out_unlock: |
212 | rtnl_unlock(); | 169 | rtnl_unlock(); |
213 | dev_put(dev); | 170 | dev_put(dev); |