Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1271622 > unrolled thread

[PATCHSET] netfilter, cgroup: implement xt_cgroup2 match

Started byTejun Heo <tj@kernel.org>
First post2015-11-17 20:50 +0100
Last post2015-11-18 00:10 +0100
Articles 12 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCHSET] netfilter, cgroup: implement xt_cgroup2 match Tejun Heo <tj@kernel.org> - 2015-11-17 20:50 +0100
    [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Tejun Heo <tj@kernel.org> - 2015-11-17 20:50 +0100
      Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup David Miller <davem@davemloft.net> - 2015-11-17 22:30 +0100
        Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Tejun Heo <tj@kernel.org> - 2015-11-17 22:40 +0100
          Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Daniel Borkmann <daniel@iogearbox.net> - 2015-11-17 22:50 +0100
            Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Tejun Heo <tj@kernel.org> - 2015-11-17 23:20 +0100
          Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup David Miller <davem@davemloft.net> - 2015-11-17 22:50 +0100
      Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Daniel Borkmann <daniel@iogearbox.net> - 2015-11-17 22:50 +0100
        Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup Tejun Heo <tj@kernel.org> - 2015-11-17 23:30 +0100
    [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it Tejun Heo <tj@kernel.org> - 2015-11-17 20:50 +0100
      Re: [PATCH 1/5] cgroup: record ancestor IDs and reimplement  cgroup_is_descendant() using it Jan Engelhardt <jengelh@inai.de> - 2015-11-18 00:00 +0100
        Re: [PATCH 1/5] cgroup: record ancestor IDs and reimplement  cgroup_is_descendant() using it Tejun Heo <tj@kernel.org> - 2015-11-18 00:10 +0100

#1271622 — [PATCHSET] netfilter, cgroup: implement xt_cgroup2 match

FromTejun Heo <tj@kernel.org>
Date2015-11-17 20:50 +0100
Subject[PATCHSET] netfilter, cgroup: implement xt_cgroup2 match
Message-ID<qvUqm-TY-5@gated-at.bofh.it>
Hello,

In cgroup v1, dealing with cgroup membership was difficult because the
number of membership associations was unbound.  As a result, cgroup v1
grew several controllers whose primary purpose is either tagging
membership or pull in configuration knobs from other subsystems so
that cgroup membership test can be avoided.

net_cls and net_prio controllers are examples of the latter.  They
allow configuring network-specific attributes from cgroup side so that
network subsystem can avoid testing cgroup membership; unfortunately,
these are not only cumbersome but also problematic.

Both net_cls and net_prio aren't properly hierarchical.  Both inherit
configuration from the parent on creation but there's no interaction
afterwards.  An ancestor doesn't restrict the behavior in its subtree
in anyway and configuration changes aren't propagated downwards.
Especially when combined with cgroup delegation, this is problematic
because delegatees can mess up whatever network configuration
implemented at the system level.  net_prio would allow the delegatees
to set whatever priority value regardless of CAP_NET_ADMIN and net_cls
the same for classid.

While it is possible to solve these issues from controller side by
implementing hierarchical allowable ranges in both controllers, it
would involve quite a bit of complexity in the controllers and further
obfuscate network configuration as it becomes even more difficult to
tell what's actually being configured looking from the network side.
While not much can be done for v1 at this point, as membership
handling is sane on cgroup v2, it'd be better to make cgroup matching
behave like other network matches and classifiers than introducing
further complications.

Unfortunately, this ends up adding another cgroup related field to
struct sock - sock->sk_cgroup.  I tried to think of a way to overload
the fields for net_cls and net_prio but couldn't come up with a sane
way to do that.  In the long term, it should be possible to disable
net_cls and net_prio.

This patchset includes the following five patches.

 0001-cgroup-record-ancestor-IDs-and-reimplement-cgroup_is.patch
 0002-kernfs-implement-kernfs_walk_and_get.patch
 0003-cgroup-implement-cgroup_get_from_path-and-expose-cgr.patch
 0004-sock-cgroup-add-sock-sk_cgroup.patch
 0005-netfilter-implement-xt_cgroup2-match.patch

0001-0003 are prepatory patches in kernfs and cgroup.  0004 adds
sock->sk_cgroup to track socket to cgroup association.  0005
implements the new xt_cgroup2 match.

This patchset is on top of v4.4-rc1 and also available in the
following git branch.

 git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-xt_cgroup2

I'll post iptables extension as a reply.  diffstat follows.  Thanks.

 fs/kernfs/dir.c                           |   48 +++++++++++++++
 include/linux/cgroup-defs.h               |   14 ++++
 include/linux/cgroup.h                    |   33 ++++++++++
 include/linux/kernfs.h                    |   12 +++
 include/net/sock.h                        |    4 +
 include/uapi/linux/netfilter/xt_cgroup2.h |   14 ++++
 kernel/cgroup.c                           |   95 +++++++++++++++++++++---------
 net/core/sock.c                           |    2 
 net/netfilter/Kconfig                     |    9 ++
 net/netfilter/Makefile                    |    1 
 net/netfilter/xt_cgroup2.c                |   75 +++++++++++++++++++++++
 11 files changed, 278 insertions(+), 29 deletions(-)

--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1271623 — [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromTejun Heo <tj@kernel.org>
Date2015-11-17 20:50 +0100
Subject[PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvUqn-TY-33@gated-at.bofh.it>
In reply to#1271622
In cgroup v1, dealing with cgroup membership was difficult because the
number of membership associations was unbound.  As a result, cgroup v1
grew several controllers whose primary purpose is either tagging
membership or pull in configuration knobs from other subsystems so
that cgroup membership test can be avoided.

net_cls and net_prio controllers are examples of the latter.  They
allow configuring network-specific attributes from cgroup side so that
network subsystem can avoid testing cgroup membership; unfortunately,
these are not only cumbersome but also problematic.

Both net_cls and net_prio aren't properly hierarchical.  Both inherit
configuration from the parent on creation but there's no interaction
afterwards.  An ancestor doesn't restrict the behavior in its subtree
in anyway and configuration changes aren't propagated downwards.
Especially when combined with cgroup delegation, this is problematic
because delegatees can mess up whatever network configuration
implemented at the system level.  net_prio would allow the delegatees
to set whatever priority value regardless of CAP_NET_ADMIN and net_cls
the same for classid.

While it is possible to solve these issues from controller side by
implementing hierarchical allowable ranges in both controllers, it
would involve quite a bit of complexity in the controllers and further
obfuscate network configuration as it becomes even more difficult to
tell what's actually being configured looking from the network side.
While not much can be done for v1 at this point, as membership
handling is sane on cgroup v2, it'd be better to make cgroup matching
behave like other network matches and classifiers than introducing
further complications.

In preparation, this patch adds sock->sk_cgroup which points to the
associated cgroup.  A sock is associated on creation and stays
associated to the same cgroup until freed; unfortunately, this ends up
adding another cgroup field to struct sock on top of sk_cgrp_prioidx
and sk_classid.  I tried to think of a way to somehow overload the
existing fields but couldn't come up with a reasonable one.  For the
longer term, the fields can be rearranged so that disabling prio and
cls controllers reduce the size of the struct.

This patch doesn't make use of the added field yet.  The following
patch will implement netfilter match for cgroup2 membership.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Daniel Wagner <daniel.wagner@bmw-carit.de>
CC: Neil Horman <nhorman@tuxdriver.com>
---
 include/linux/cgroup.h |  8 ++++++++
 include/net/sock.h     |  4 ++++
 kernel/cgroup.c        | 25 ++++++++++++++++++++++++-
 net/core/sock.c        |  2 ++
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 4c3ffab..2a6d7c4 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -20,6 +20,8 @@
 
 #include <linux/cgroup-defs.h>
 
+struct sock;
+
 #ifdef CONFIG_CGROUPS
 
 /*
@@ -108,6 +110,9 @@ void cgroup_free(struct task_struct *p);
 int cgroup_init_early(void);
 int cgroup_init(void);
 
+void cgroup_sk_alloc(struct sock *sk);
+void cgroup_sk_free(struct sock *sk);
+
 /*
  * Iteration helpers and macros.
  */
@@ -576,6 +581,9 @@ static inline void cgroup_free(struct task_struct *p) {}
 static inline int cgroup_init_early(void) { return 0; }
 static inline int cgroup_init(void) { return 0; }
 
+static inline void cgroup_sk_alloc(struct sock *sk) {}
+static inline void cgroup_sk_free(struct sock *sk) {}
+
 #endif /* !CONFIG_CGROUPS */
 
 #endif /* _LINUX_CGROUP_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index bbf7c2c..6c5d195 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -310,6 +310,7 @@ struct cg_proto;
   *	@sk_security: used by security modules
   *	@sk_mark: generic packet mark
   *	@sk_classid: this socket's cgroup classid
+  *	@sk_cgroup: the v2 cgroup this socket is associated with
   *	@sk_cgrp: this socket's cgroup-specific proto data
   *	@sk_write_pending: a write to stream socket waits to start
   *	@sk_state_change: callback to indicate change in the state of the sock
@@ -447,6 +448,9 @@ struct sock {
 #ifdef CONFIG_CGROUP_NET_CLASSID
 	u32			sk_classid;
 #endif
+#ifdef CONFIG_CGROUPS
+	struct cgroup		*sk_cgroup;
+#endif
 	struct cg_proto		*sk_cgrp;
 	void			(*sk_state_change)(struct sock *sk);
 	void			(*sk_data_ready)(struct sock *sk);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 49947c1..f26533b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -57,8 +57,8 @@
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
 #include <linux/kthread.h>
 #include <linux/delay.h>
-
 #include <linux/atomic.h>
+#include <net/sock.h>
 
 /*
  * pidlists linger the following amount before being destroyed.  The goal
@@ -5781,6 +5781,29 @@ struct cgroup *cgroup_get_from_path(const char *path)
 	return cgrp;
 }
 
+void cgroup_sk_alloc(struct sock *sk)
+{
+	rcu_read_lock();
+
+	while (true) {
+		struct css_set *cset;
+
+		cset = task_css_set(current);
+		if (likely(cgroup_tryget(cset->dfl_cgrp))) {
+			sk->sk_cgroup = cset->dfl_cgrp;
+			break;
+		}
+		cpu_relax();
+	}
+
+	rcu_read_unlock();
+}
+
+void cgroup_sk_free(struct sock *sk)
+{
+	cgroup_put(sk->sk_cgroup);
+}
+
 #ifdef CONFIG_CGROUP_DEBUG
 static struct cgroup_subsys_state *
 debug_css_alloc(struct cgroup_subsys_state *parent_css)
diff --git a/net/core/sock.c b/net/core/sock.c
index 1e4dd54..7c34bba 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1363,6 +1363,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
 		if (!try_module_get(prot->owner))
 			goto out_free_sec;
 		sk_tx_queue_clear(sk);
+		cgroup_sk_alloc(sk);
 	}
 
 	return sk;
@@ -1385,6 +1386,7 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 	owner = prot->owner;
 	slab = prot->slab;
 
+	cgroup_sk_free(sk);
 	security_sk_free(sk);
 	if (slab != NULL)
 		kmem_cache_free(slab, sk);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271669 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromDavid Miller <davem@davemloft.net>
Date2015-11-17 22:30 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvVZ8-20O-29@gated-at.bofh.it>
In reply to#1271623
From: Tejun Heo <tj@kernel.org>
Date: Tue, 17 Nov 2015 14:40:39 -0500

> In preparation, this patch adds sock->sk_cgroup which points to the
> associated cgroup.  A sock is associated on creation and stays
> associated to the same cgroup until freed; unfortunately, this ends up
> adding another cgroup field to struct sock on top of sk_cgrp_prioidx
> and sk_classid.  I tried to think of a way to somehow overload the
> existing fields but couldn't come up with a reasonable one.

sk->sk_cgrp_prioidx is simply sk->sk_cgroup->id, is it not?

We really need to consolidate this before we stuff even more members
into the socket for control group support, sorry.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271681 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromTejun Heo <tj@kernel.org>
Date2015-11-17 22:40 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvW8P-24z-33@gated-at.bofh.it>
In reply to#1271669
Hello, David.

On Tue, Nov 17, 2015 at 04:25:54PM -0500, David Miller wrote:
> > In preparation, this patch adds sock->sk_cgroup which points to the
> > associated cgroup.  A sock is associated on creation and stays
> > associated to the same cgroup until freed; unfortunately, this ends up
> > adding another cgroup field to struct sock on top of sk_cgrp_prioidx
> > and sk_classid.  I tried to think of a way to somehow overload the
> > existing fields but couldn't come up with a reasonable one.
> 
> sk->sk_cgrp_prioidx is simply sk->sk_cgroup->id, is it not?

Unfortunately, sk->sk_cgrp_prioidx is an arbitrary value which can be
configured through "net_cls.classid".  :(

> We really need to consolidate this before we stuff even more members
> into the socket for control group support, sorry.

Yeah, it is messy.  I'll see if I can come up with a non-crazy way to
combine the other two fields with ->sk_cgroup.

Thanks.

-- 
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271686 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromDaniel Borkmann <daniel@iogearbox.net>
Date2015-11-17 22:50 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvWiv-28b-15@gated-at.bofh.it>
In reply to#1271681
On 11/17/2015 10:31 PM, Tejun Heo wrote:
> Hello, David.
>
> On Tue, Nov 17, 2015 at 04:25:54PM -0500, David Miller wrote:
>>> In preparation, this patch adds sock->sk_cgroup which points to the
>>> associated cgroup.  A sock is associated on creation and stays
>>> associated to the same cgroup until freed; unfortunately, this ends up
>>> adding another cgroup field to struct sock on top of sk_cgrp_prioidx
>>> and sk_classid.  I tried to think of a way to somehow overload the
>>> existing fields but couldn't come up with a reasonable one.
>>
>> sk->sk_cgrp_prioidx is simply sk->sk_cgroup->id, is it not?
>
> Unfortunately, sk->sk_cgrp_prioidx is an arbitrary value which can be
> configured through "net_cls.classid".  :(

Hmm, isn't net_prio independent of net_cls?

>> We really need to consolidate this before we stuff even more members
>> into the socket for control group support, sorry.
>
> Yeah, it is messy.  I'll see if I can come up with a non-crazy way to
> combine the other two fields with ->sk_cgroup.
>
> Thanks.
>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271698 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromTejun Heo <tj@kernel.org>
Date2015-11-17 23:20 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvWLw-2zc-11@gated-at.bofh.it>
In reply to#1271686
Hello, Daniel.

On Tue, Nov 17, 2015 at 10:48:46PM +0100, Daniel Borkmann wrote:
> >Unfortunately, sk->sk_cgrp_prioidx is an arbitrary value which can be
> >configured through "net_cls.classid".  :(
> 
> Hmm, isn't net_prio independent of net_cls?

Ah, yeah, I was mixing up the two but the story is the same for both.
net_prio configures the prioidx and net_cls the classid and the two
may or may not (but more likely not) be on the same hierarchy and
definitely not on the cgroup2 hierarchy, so you can't really access
them through a single ->sk_cgroup pointer.  After all, that's why we
ended up with these controllers.

Thanks.

-- 
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271688 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromDavid Miller <davem@davemloft.net>
Date2015-11-17 22:50 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvWiv-28b-19@gated-at.bofh.it>
In reply to#1271681
From: Tejun Heo <tj@kernel.org>
Date: Tue, 17 Nov 2015 16:31:26 -0500

> I'll see if I can come up with a non-crazy way to combine the other
> two fields with ->sk_cgroup.

Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271685 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromDaniel Borkmann <daniel@iogearbox.net>
Date2015-11-17 22:50 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvWiv-28b-13@gated-at.bofh.it>
In reply to#1271623
Hi Tejun,

On 11/17/2015 08:40 PM, Tejun Heo wrote:
...
> While it is possible to solve these issues from controller side by
> implementing hierarchical allowable ranges in both controllers, it
> would involve quite a bit of complexity in the controllers and further
> obfuscate network configuration as it becomes even more difficult to
> tell what's actually being configured looking from the network side.
> While not much can be done for v1 at this point, as membership
> handling is sane on cgroup v2, it'd be better to make cgroup matching
> behave like other network matches and classifiers than introducing
> further complications.
>
> In preparation, this patch adds sock->sk_cgroup which points to the
> associated cgroup.  A sock is associated on creation and stays
> associated to the same cgroup until freed; unfortunately, this ends up
> adding another cgroup field to struct sock on top of sk_cgrp_prioidx
> and sk_classid.  I tried to think of a way to somehow overload the
> existing fields but couldn't come up with a reasonable one.  For the
> longer term, the fields can be rearranged so that disabling prio and
> cls controllers reduce the size of the struct.

Do you see a way forward where the new behavior could be enabled f.e.
as an extra mount option (that long-term would be made default, while
deprecating the current behavior) on net_cls et al? There are various
more users at least on the net_cls side (nft and tc as well). Would be
really great, if sk_cgroup could abstract that somehow away for all of
them w/o adding a second version to all users.

Best,
Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271703 — Re: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup

FromTejun Heo <tj@kernel.org>
Date2015-11-17 23:30 +0100
SubjectRe: [PATCH 4/5] sock, cgroup: add sock->sk_cgroup
Message-ID<qvWVb-2Cu-7@gated-at.bofh.it>
In reply to#1271685
Hello, Daniel.

On Tue, Nov 17, 2015 at 10:46:30PM +0100, Daniel Borkmann wrote:
> Do you see a way forward where the new behavior could be enabled f.e.
> as an extra mount option (that long-term would be made default, while
> deprecating the current behavior) on net_cls et al? There are various
> more users at least on the net_cls side (nft and tc as well). Would be
> really great, if sk_cgroup could abstract that somehow away for all of
> them w/o adding a second version to all users.

I'm not really sure I'm following what you mean but no matter how we
go about it net_cls and prio won't be broken.  I likely will end up
making the two sets mutually exclusive once configured run-time but
there's no reason to use both at the same time anyway.

Thanks.

-- 
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271624 — [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it

FromTejun Heo <tj@kernel.org>
Date2015-11-17 20:50 +0100
Subject[PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it
Message-ID<qvUqn-TY-37@gated-at.bofh.it>
In reply to#1271622
cgroup_is_descendant() currently walks up the hierarchy and compares
each ancestor to the cgroup in question.  While enough for cgroup core
usages, this can't be used in hot paths to test cgroup membership.
This patch adds cgroup->ancestor_ids[] which records the IDs of all
ancestors including self and cgroup->level for the nesting level.

This allows testing whether a given cgroup is a descendant of another
in three finite steps - testing whether the two belong to the same
hierarchy, whether the descendant candidate is at the same or a higher
level than the ancestor and comparing the recorded ancestor_id at the
matching level.  cgroup_is_descendant() is accordingly reimplmented
and made inline.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 include/linux/cgroup-defs.h | 14 ++++++++++++++
 include/linux/cgroup.h      | 18 +++++++++++++++++-
 kernel/cgroup.c             | 32 ++++++++++----------------------
 3 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 60d44b2..504d859 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -235,6 +235,14 @@ struct cgroup {
 	int id;
 
 	/*
+	 * The depth this cgroup is at.  The root is at depth zero and each
+	 * step down the hierarchy increments the level.  This along with
+	 * ancestor_ids[] can determine whether a given cgroup is a
+	 * descendant of another without traversing the hierarchy.
+	 */
+	int level;
+
+	/*
 	 * Each non-empty css_set associated with this cgroup contributes
 	 * one to populated_cnt.  All children with non-zero popuplated_cnt
 	 * of their own contribute one.  The count is zero iff there's no
@@ -289,6 +297,9 @@ struct cgroup {
 
 	/* used to schedule release agent */
 	struct work_struct release_agent_work;
+
+	/* ids of the ancestors at each level including self */
+	int ancestor_ids[];
 };
 
 /*
@@ -308,6 +319,9 @@ struct cgroup_root {
 	/* The root cgroup.  Root is destroyed on its release. */
 	struct cgroup cgrp;
 
+	/* for cgrp->ancestor_ids[0] */
+	int cgrp_ancestor_id_storage;
+
 	/* Number of cgroups in the hierarchy, used only for /proc/cgroups */
 	atomic_t nr_cgrps;
 
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 22e3754..b5ee2c4 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -81,7 +81,6 @@ struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup,
 struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
 						       struct cgroup_subsys *ss);
 
-bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
 
@@ -459,6 +458,23 @@ static inline struct cgroup *task_cgroup(struct task_struct *task,
 	return task_css(task, subsys_id)->cgroup;
 }
 
+/**
+ * cgroup_is_descendant - test ancestry
+ * @cgrp: the cgroup to be tested
+ * @ancestor: possible ancestor of @cgrp
+ *
+ * Test whether @cgrp is a descendant of @ancestor.  It also returns %true
+ * if @cgrp == @ancestor.  This function is safe to call as long as @cgrp
+ * and @ancestor are accessible.
+ */
+static inline bool cgroup_is_descendant(struct cgroup *cgrp,
+					struct cgroup *ancestor)
+{
+	if (cgrp->root != ancestor->root || cgrp->level < ancestor->level)
+		return false;
+	return cgrp->ancestor_ids[ancestor->level] == ancestor->id;
+}
+
 /* no synchronization, the result can only be used as a hint */
 static inline bool cgroup_is_populated(struct cgroup *cgrp)
 {
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f1603c1..3190040 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -459,25 +459,6 @@ struct cgroup_subsys_state *of_css(struct kernfs_open_file *of)
 }
 EXPORT_SYMBOL_GPL(of_css);
 
-/**
- * cgroup_is_descendant - test ancestry
- * @cgrp: the cgroup to be tested
- * @ancestor: possible ancestor of @cgrp
- *
- * Test whether @cgrp is a descendant of @ancestor.  It also returns %true
- * if @cgrp == @ancestor.  This function is safe to call as long as @cgrp
- * and @ancestor are accessible.
- */
-bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor)
-{
-	while (cgrp) {
-		if (cgrp == ancestor)
-			return true;
-		cgrp = cgroup_parent(cgrp);
-	}
-	return false;
-}
-
 static int notify_on_release(const struct cgroup *cgrp)
 {
 	return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
@@ -1903,6 +1884,7 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned long ss_mask)
 	if (ret < 0)
 		goto out;
 	root_cgrp->id = ret;
+	root_cgrp->ancestor_ids[0] = ret;
 
 	ret = percpu_ref_init(&root_cgrp->self.refcnt, css_release, 0,
 			      GFP_KERNEL);
@@ -4846,11 +4828,11 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss,
 static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 			umode_t mode)
 {
-	struct cgroup *parent, *cgrp;
+	struct cgroup *parent, *cgrp, *tcgrp;
 	struct cgroup_root *root;
 	struct cgroup_subsys *ss;
 	struct kernfs_node *kn;
-	int ssid, ret;
+	int level, ssid, ret;
 
 	/* Do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable.
 	 */
@@ -4861,9 +4843,11 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 	if (!parent)
 		return -ENODEV;
 	root = parent->root;
+	level = parent->level + 1;
 
 	/* allocate the cgroup and its ID, 0 is reserved for the root */
-	cgrp = kzalloc(sizeof(*cgrp), GFP_KERNEL);
+	cgrp = kzalloc(sizeof(*cgrp) +
+		       sizeof(cgrp->ancestor_ids[0]) * (level + 1), GFP_KERNEL);
 	if (!cgrp) {
 		ret = -ENOMEM;
 		goto out_unlock;
@@ -4887,6 +4871,10 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
 
 	cgrp->self.parent = &parent->self;
 	cgrp->root = root;
+	cgrp->level = level;
+
+	for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp))
+		cgrp->ancestor_ids[tcgrp->level] = tcgrp->id;
 
 	if (notify_on_release(parent))
 		set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271720 — Re: [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it

FromJan Engelhardt <jengelh@inai.de>
Date2015-11-18 00:00 +0100
SubjectRe: [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it
Message-ID<qvXoe-2MS-17@gated-at.bofh.it>
In reply to#1271624
On Tuesday 2015-11-17 20:40, Tejun Heo wrote:
>+static inline bool cgroup_is_descendant(struct cgroup *cgrp,
>+					struct cgroup *ancestor)

(const struct group *cgrp, const struct group *ancestor)

>+{
>+	if (cgrp->root != ancestor->root || cgrp->level < ancestor->level)
>+		return false;
>+	return cgrp->ancestor_ids[ancestor->level] == ancestor->id;
>+}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271729 — Re: [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it

FromTejun Heo <tj@kernel.org>
Date2015-11-18 00:10 +0100
SubjectRe: [PATCH 1/5] cgroup: record ancestor IDs and reimplement cgroup_is_descendant() using it
Message-ID<qvXxU-36Y-27@gated-at.bofh.it>
In reply to#1271720
On Tue, Nov 17, 2015 at 11:54:54PM +0100, Jan Engelhardt wrote:
> 
> On Tuesday 2015-11-17 20:40, Tejun Heo wrote:
> >+static inline bool cgroup_is_descendant(struct cgroup *cgrp,
> >+					struct cgroup *ancestor)
> 
> (const struct group *cgrp, const struct group *ancestor)

I'm not sure about using const on complex data structures.  It often
ends up causing more mess than being helpful.  It's never consistent
and often can't be - e.g. you throw in an iteration macro and then
realize that there need to be two separate variants of iteration
macros for consts and !consts after propagating const through the call
chains and then end up doing forced casts.

Thanks.

-- 
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web