Browse Source

netprio_cgroup: allow nesting and inherit config on cgroup creation

Inherit netprio configuration from ->css_online(), allow nesting and
remove .broken_hierarchy marking.  This makes netprio_cgroup's
behavior match netcls_cgroup's.

Note that this patch changes userland-visible behavior.  Nesting is
allowed and the first level cgroups below the root cgroup behave
differently - they inherit priorities from the root cgroup on creation
instead of starting with 0.  This is unfortunate but not doing so is
much crazier.

Signed-off-by: Tejun Heo <tj@kernel.org>
Tested-and-Acked-by: Daniel Wagner <daniel.wagner@bmw-carit.de>
Acked-by: David S. Miller <davem@davemloft.net>
Tejun Heo 13 years ago
parent
commit
811d8d6ff5
2 changed files with 26 additions and 18 deletions
  1. 2 0
      Documentation/cgroups/net_prio.txt
  2. 24 18
      net/core/netprio_cgroup.c

+ 2 - 0
Documentation/cgroups/net_prio.txt

@@ -51,3 +51,5 @@ One usage for the net_prio cgroup is with mqprio qdisc allowing application
 traffic to be steered to hardware/driver based traffic classes. These mappings
 traffic to be steered to hardware/driver based traffic classes. These mappings
 can then be managed by administrators or other networking protocols such as
 can then be managed by administrators or other networking protocols such as
 DCBX.
 DCBX.
+
+A new net_prio cgroup inherits the parent's configuration.

+ 24 - 18
net/core/netprio_cgroup.c

@@ -136,9 +136,6 @@ static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp)
 {
 {
 	struct cgroup_netprio_state *cs;
 	struct cgroup_netprio_state *cs;
 
 
-	if (cgrp->parent && cgrp->parent->id)
-		return ERR_PTR(-EINVAL);
-
 	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 	if (!cs)
 	if (!cs)
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
@@ -146,16 +143,34 @@ static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp)
 	return &cs->css;
 	return &cs->css;
 }
 }
 
 
-static void cgrp_css_free(struct cgroup *cgrp)
+static int cgrp_css_online(struct cgroup *cgrp)
 {
 {
-	struct cgroup_netprio_state *cs = cgrp_netprio_state(cgrp);
+	struct cgroup *parent = cgrp->parent;
 	struct net_device *dev;
 	struct net_device *dev;
+	int ret = 0;
+
+	if (!parent)
+		return 0;
 
 
 	rtnl_lock();
 	rtnl_lock();
-	for_each_netdev(&init_net, dev)
-		WARN_ON_ONCE(netprio_set_prio(cgrp, dev, 0));
+	/*
+	 * Inherit prios from the parent.  As all prios are set during
+	 * onlining, there is no need to clear them on offline.
+	 */
+	for_each_netdev(&init_net, dev) {
+		u32 prio = netprio_prio(parent, dev);
+
+		ret = netprio_set_prio(cgrp, dev, prio);
+		if (ret)
+			break;
+	}
 	rtnl_unlock();
 	rtnl_unlock();
-	kfree(cs);
+	return ret;
+}
+
+static void cgrp_css_free(struct cgroup *cgrp)
+{
+	kfree(cgrp_netprio_state(cgrp));
 }
 }
 
 
 static u64 read_prioidx(struct cgroup *cgrp, struct cftype *cft)
 static u64 read_prioidx(struct cgroup *cgrp, struct cftype *cft)
@@ -237,21 +252,12 @@ static struct cftype ss_files[] = {
 struct cgroup_subsys net_prio_subsys = {
 struct cgroup_subsys net_prio_subsys = {
 	.name		= "net_prio",
 	.name		= "net_prio",
 	.css_alloc	= cgrp_css_alloc,
 	.css_alloc	= cgrp_css_alloc,
+	.css_online	= cgrp_css_online,
 	.css_free	= cgrp_css_free,
 	.css_free	= cgrp_css_free,
 	.attach		= net_prio_attach,
 	.attach		= net_prio_attach,
 	.subsys_id	= net_prio_subsys_id,
 	.subsys_id	= net_prio_subsys_id,
 	.base_cftypes	= ss_files,
 	.base_cftypes	= ss_files,
 	.module		= THIS_MODULE,
 	.module		= THIS_MODULE,
-
-	/*
-	 * net_prio has artificial limit on the number of cgroups and
-	 * disallows nesting making it impossible to co-mount it with other
-	 * hierarchical subsystems.  Remove the artificially low PRIOIDX_SZ
-	 * limit and properly nest configuration such that children follow
-	 * their parents' configurations by default and are allowed to
-	 * override and remove the following.
-	 */
-	.broken_hierarchy = true,
 };
 };
 
 
 static int netprio_device_event(struct notifier_block *unused,
 static int netprio_device_event(struct notifier_block *unused,