Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netprio_cgroup: implement netprio[_set]_prio() helpers

Introduce two helpers - netprio_prio() and netprio_set_prio() - which
hide the details of priomap access and expansion. This will help
implementing hierarchy support.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Tested-and-Acked-by: Daniel Wagner <daniel.wagner@bmw-carit.de>
Acked-by: David S. Miller <davem@davemloft.net>

Tejun Heo 666b0ebe 88d642fa

+50 -22
+50 -22
net/core/netprio_cgroup.c
··· 87 87 return 0; 88 88 } 89 89 90 + /** 91 + * netprio_prio - return the effective netprio of a cgroup-net_device pair 92 + * @cgrp: cgroup part of the target pair 93 + * @dev: net_device part of the target pair 94 + * 95 + * Should be called under RCU read or rtnl lock. 96 + */ 97 + static u32 netprio_prio(struct cgroup *cgrp, struct net_device *dev) 98 + { 99 + struct netprio_map *map = rcu_dereference_rtnl(dev->priomap); 100 + 101 + if (map && cgrp->id < map->priomap_len) 102 + return map->priomap[cgrp->id]; 103 + return 0; 104 + } 105 + 106 + /** 107 + * netprio_set_prio - set netprio on a cgroup-net_device pair 108 + * @cgrp: cgroup part of the target pair 109 + * @dev: net_device part of the target pair 110 + * @prio: prio to set 111 + * 112 + * Set netprio to @prio on @cgrp-@dev pair. Should be called under rtnl 113 + * lock and may fail under memory pressure for non-zero @prio. 114 + */ 115 + static int netprio_set_prio(struct cgroup *cgrp, struct net_device *dev, 116 + u32 prio) 117 + { 118 + struct netprio_map *map; 119 + int ret; 120 + 121 + /* avoid extending priomap for zero writes */ 122 + map = rtnl_dereference(dev->priomap); 123 + if (!prio && (!map || map->priomap_len <= cgrp->id)) 124 + return 0; 125 + 126 + ret = extend_netdev_table(dev, cgrp->id); 127 + if (ret) 128 + return ret; 129 + 130 + map = rtnl_dereference(dev->priomap); 131 + map->priomap[cgrp->id] = prio; 132 + return 0; 133 + } 134 + 90 135 static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp) 91 136 { 92 137 struct cgroup_netprio_state *cs; ··· 150 105 { 151 106 struct cgroup_netprio_state *cs = cgrp_netprio_state(cgrp); 152 107 struct net_device *dev; 153 - struct netprio_map *map; 154 108 155 109 rtnl_lock(); 156 - for_each_netdev(&init_net, dev) { 157 - map = rtnl_dereference(dev->priomap); 158 - if (map && cgrp->id < map->priomap_len) 159 - map->priomap[cgrp->id] = 0; 160 - } 110 + for_each_netdev(&init_net, dev) 111 + WARN_ON_ONCE(netprio_set_prio(cgrp, dev, 0)); 161 112 rtnl_unlock(); 162 113 kfree(cs); 163 114 } ··· 167 126 struct cgroup_map_cb *cb) 168 127 { 169 128 struct net_device *dev; 170 - u32 id = cont->id; 171 - u32 priority; 172 - struct netprio_map *map; 173 129 174 130 rcu_read_lock(); 175 - for_each_netdev_rcu(&init_net, dev) { 176 - map = rcu_dereference(dev->priomap); 177 - priority = (map && id < map->priomap_len) ? map->priomap[id] : 0; 178 - cb->fill(cb, dev->name, priority); 179 - } 131 + for_each_netdev_rcu(&init_net, dev) 132 + cb->fill(cb, dev->name, netprio_prio(cont, dev)); 180 133 rcu_read_unlock(); 181 134 return 0; 182 135 } ··· 180 145 { 181 146 char devname[IFNAMSIZ + 1]; 182 147 struct net_device *dev; 183 - struct netprio_map *map; 184 148 u32 prio; 185 149 int ret; 186 150 ··· 192 158 193 159 rtnl_lock(); 194 160 195 - ret = extend_netdev_table(dev, cgrp->id); 196 - if (ret) 197 - goto out_unlock; 161 + ret = netprio_set_prio(cgrp, dev, prio); 198 162 199 - map = rtnl_dereference(dev->priomap); 200 - if (map) 201 - map->priomap[cgrp->id] = prio; 202 - out_unlock: 203 163 rtnl_unlock(); 204 164 dev_put(dev); 205 165 return ret;