aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netprio_cgroup.h11
-rw-r--r--net/core/netprio_cgroup.c65
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
28struct cgroup_netprio_state { 28struct cgroup_netprio_state {
29 struct cgroup_subsys_state css; 29 struct cgroup_subsys_state css;
30 u32 prioidx;
31}; 30};
32 31
33extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); 32extern 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
37static inline u32 task_netprioidx(struct task_struct *p) 36static 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
33static unsigned long prioidx_map[PRIOIDX_SZ];
34static DEFINE_SPINLOCK(prioidx_map_lock);
35 31
36static inline struct cgroup_netprio_state *cgrp_netprio_state(struct cgroup *cgrp) 32static 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
42static 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
59static 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)
120static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp) 90static 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;
139out:
140 kfree(cs);
141 return ERR_PTR(ret);
142} 102}
143 103
144static void cgrp_css_free(struct cgroup *cgrp) 104static 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
162static u64 read_prioidx(struct cgroup *cgrp, struct cftype *cft) 120static 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
167static int read_priomap(struct cgroup *cont, struct cftype *cft, 125static 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,
185static int write_priomap(struct cgroup *cgrp, struct cftype *cft, 143static 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;
211out_unlock: 168out_unlock:
212 rtnl_unlock(); 169 rtnl_unlock();
213 dev_put(dev); 170 dev_put(dev);