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


Groups > linux.kernel > #1270530 > unrolled thread

CGroup Namespaces (v4)

Started byserge@hallyn.com
First post2015-11-16 21:00 +0100
Last post2015-11-16 21:50 +0100
Articles 20 on this page of 27 — 7 participants

Back to article view | Back to linux.kernel


Contents

  CGroup Namespaces (v4) serge@hallyn.com - 2015-11-16 21:00 +0100
    [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put() serge@hallyn.com - 2015-11-16 21:00 +0100
      Re: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put() Tejun Heo <tj@kernel.org> - 2015-11-24 17:40 +0100
        Re: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put() "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-11-24 23:40 +0100
    [PATCH 6/8] cgroup: cgroup namespace setns support serge@hallyn.com - 2015-11-16 21:00 +0100
      Re: [PATCH 6/8] cgroup: cgroup namespace setns support Tejun Heo <tj@kernel.org> - 2015-11-24 18:00 +0100
    [PATCH 1/8] kernfs: Add API to generate relative kernfs path serge@hallyn.com - 2015-11-16 21:00 +0100
      Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path Tejun Heo <tj@kernel.org> - 2015-11-24 17:20 +0100
        Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-11-24 18:50 +0100
      Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path Tejun Heo <tj@kernel.org> - 2015-11-24 17:20 +0100
        Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-11-27 06:30 +0100
          Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path Tejun Heo <tj@kernel.org> - 2015-11-30 16:20 +0100
            Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-11-30 19:40 +0100
              Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path Tejun Heo <tj@kernel.org> - 2015-12-01 00:00 +0100
                Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-12-01 03:10 +0100
    Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-16 21:50 +0100
      Re: CGroup Namespaces (v4) Richard Weinberger <richard@nod.at> - 2015-11-16 22:00 +0100
        Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-16 22:00 +0100
          Re: CGroup Namespaces (v4) ebiederm@xmission.com (Eric W. Biederman) - 2015-11-16 23:40 +0100
            Re: CGroup Namespaces (v4) Tejun Heo <tj@kernel.org> - 2015-11-16 23:40 +0100
            Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-17 02:20 +0100
              Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-17 02:50 +0100
                Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-17 05:00 +0100
            Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge@hallyn.com> - 2015-11-18 03:40 +0100
              Re: CGroup Namespaces (v4) ebiederm@xmission.com (Eric W. Biederman) - 2015-11-18 10:30 +0100
                Re: CGroup Namespaces (v4) "Serge E. Hallyn" <serge.hallyn@ubuntu.com> - 2015-11-18 16:50 +0100
    Re: CGroup Namespaces (v4) Richard Weinberger <richard.weinberger@gmail.com> - 2015-11-16 21:50 +0100

Page 1 of 2  [1] 2  Next page →


#1270530 — CGroup Namespaces (v4)

Fromserge@hallyn.com
Date2015-11-16 21:00 +0100
SubjectCGroup Namespaces (v4)
Message-ID<qvy6u-3b3-3@gated-at.bofh.it>
Hi,

following is a revised set of the CGroup Namespace patchset which Aditya
Kali has previously sent.  The code can also be found in the cgroupns.v4
branch of

https://git.kernel.org/cgit/linux/kernel/git/sergeh/linux-security.git/

To summarize the semantics:

1. CLONE_NEWCGROUP re-uses 0x02000000, which was previously CLONE_STOPPED

2. unsharing a cgroup namespace makes all your current cgroups your new
cgroup root.

3. /proc/pid/cgroup always shows cgroup paths relative to the reader's
cgroup namespce root.  A task outside of  your cgroup looks like

	8:memory:/../../..

4. when a task mounts a cgroupfs, the cgroup which shows up as root depends
on the mounting task's  cgroup namespace.

5. setns to a cgroup namespace switches your cgroup namespace but not
your cgroups.

With this, using github.com/hallyn/lxc #2015-11-09/cgns (and
github.com/hallyn/lxcfs #2015-11-10/cgns) we can start a container in a full
proper cgroup namespace, avoiding either cgmanager or lxcfs cgroup bind mounts.

This is completely backward compatible and will be completely invisible
to any existing cgroup users (except for those running inside a cgroup
namespace and looking at /proc/pid/cgroup of tasks outside their
namespace.)

Changes from V3:
1. Rebased onto latest cgroup changes.  In particular switch to
   css_set_lock and ns_common.
2. Support all hierarchies.

Changes from V2:
1. Added documentation in Documentation/cgroups/namespace.txt
2. Fixed a bug that caused crash
3. Incorporated some other suggestions from last patchset:
   - removed use of threadgroup_lock() while creating new cgroupns
   - use task_lock() instead of rcu_read_lock() while accessing
     task->nsproxy
   - optimized setns() to own cgroupns
   - simplified code around sane-behavior mount option parsing
4. Restored ACKs from Serge Hallyn from v1 on few patches that have
   not changed since then.

Changes from V1:
1. No pinning of processes within cgroupns. Tasks can be freely moved
   across cgroups even outside of their cgroupns-root. Usual DAC/MAC policies
   apply as before.
2. Path in /proc/<pid>/cgroup is now always shown and is relative to
   cgroupns-root. So path can contain '/..' strings depending on cgroupns-root
   of the reader and cgroup of <pid>.
3. setns() does not require the process to first move under target
   cgroupns-root.

Changes form RFC (V0):
1. setns support for cgroupns
2. 'mount -t cgroup cgroup <mntpt>' from inside a cgroupns now
   mounts the cgroup hierarcy with cgroupns-root as the filesystem root.
3. writes to cgroup files outside of cgroupns-root are not allowed
4. visibility of /proc/<pid>/cgroup is further restricted by not showing
   anything if the <pid> is in a sibling cgroupns and its cgroup falls outside
   your cgroupns-root.

--
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]


#1270534 — [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()

Fromserge@hallyn.com
Date2015-11-16 21:00 +0100
Subject[PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()
Message-ID<qvy6w-3b3-35@gated-at.bofh.it>
In reply to#1270530
From: Aditya Kali <adityakali@google.com>

move cgroup_get() and cgroup_put() into cgroup.h so that
they can be called from other places.

Signed-off-by: Aditya Kali <adityakali@google.com>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
---
 include/linux/cgroup.h |   21 +++++++++++++++++++++
 kernel/cgroup.c        |   22 ----------------------
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 29f0b02..99096be 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -231,6 +231,27 @@ void css_task_iter_end(struct css_task_iter *it);
 #define css_for_each_descendant_post(pos, css)				\
 	for ((pos) = css_next_descendant_post(NULL, (css)); (pos);	\
 	     (pos) = css_next_descendant_post((pos), (css)))
+/* convenient tests for these bits */
+static inline bool cgroup_is_dead(const struct cgroup *cgrp)
+{
+	return !(cgrp->self.flags & CSS_ONLINE);
+}
+
+static inline void cgroup_get(struct cgroup *cgrp)
+{
+	WARN_ON_ONCE(cgroup_is_dead(cgrp));
+	css_get(&cgrp->self);
+}
+
+static inline bool cgroup_tryget(struct cgroup *cgrp)
+{
+	return css_tryget(&cgrp->self);
+}
+
+static inline void cgroup_put(struct cgroup *cgrp)
+{
+	css_put(&cgrp->self);
+}
 
 /**
  * cgroup_taskset_for_each - iterate cgroup_taskset
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e29c346..e972259 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -417,28 +417,6 @@ out_unlock:
 	return css;
 }
 
-/* convenient tests for these bits */
-static inline bool cgroup_is_dead(const struct cgroup *cgrp)
-{
-	return !(cgrp->self.flags & CSS_ONLINE);
-}
-
-static void cgroup_get(struct cgroup *cgrp)
-{
-	WARN_ON_ONCE(cgroup_is_dead(cgrp));
-	css_get(&cgrp->self);
-}
-
-static bool cgroup_tryget(struct cgroup *cgrp)
-{
-	return css_tryget(&cgrp->self);
-}
-
-static void cgroup_put(struct cgroup *cgrp)
-{
-	css_put(&cgrp->self);
-}
-
 struct cgroup_subsys_state *of_css(struct kernfs_open_file *of)
 {
 	struct cgroup *cgrp = of->kn->parent->priv;
-- 
1.7.9.5

--
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]


#1276629 — Re: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()

FromTejun Heo <tj@kernel.org>
Date2015-11-24 17:40 +0100
SubjectRe: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()
Message-ID<qyoNj-29z-11@gated-at.bofh.it>
In reply to#1270534
Hello,

On Mon, Nov 16, 2015 at 01:51:41PM -0600, serge@hallyn.com wrote:
> From: Aditya Kali <adityakali@google.com>
> 
> move cgroup_get() and cgroup_put() into cgroup.h so that
> they can be called from other places.
> 
> Signed-off-by: Aditya Kali <adityakali@google.com>
> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
> ---
>  include/linux/cgroup.h |   21 +++++++++++++++++++++
>  kernel/cgroup.c        |   22 ----------------------
>  2 files changed, 21 insertions(+), 22 deletions(-)
> 
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
> index 29f0b02..99096be 100644
> --- a/include/linux/cgroup.h
> +++ b/include/linux/cgroup.h
> @@ -231,6 +231,27 @@ void css_task_iter_end(struct css_task_iter *it);
>  #define css_for_each_descendant_post(pos, css)				\
>  	for ((pos) = css_next_descendant_post(NULL, (css)); (pos);	\
>  	     (pos) = css_next_descendant_post((pos), (css)))

Please insert a blank line here.

> +/* convenient tests for these bits */

And I don't think the comment makes sense here.

> +static inline bool cgroup_is_dead(const struct cgroup *cgrp)
> +{
> +	return !(cgrp->self.flags & CSS_ONLINE);
> +}
> +
> +static inline void cgroup_get(struct cgroup *cgrp)
> +{
> +	WARN_ON_ONCE(cgroup_is_dead(cgrp));
> +	css_get(&cgrp->self);
> +}
> +
> +static inline bool cgroup_tryget(struct cgroup *cgrp)
> +{
> +	return css_tryget(&cgrp->self);
> +}
> +
> +static inline void cgroup_put(struct cgroup *cgrp)
> +{
> +	css_put(&cgrp->self);
> +}

So these are being exposed for cgroup NS support.  Hmmm... idk, does
cgroup NS support needs to be in a spearate file?  The added amount
isn't that big.  If we split cgroup.c, I'd much prefer to have
cgroup-internal.h for internally shared stuff than pushing them out to
cgroup.h.

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]


#1276832 — Re: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()

From"Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Date2015-11-24 23:40 +0100
SubjectRe: [PATCH 4/8] cgroup: export cgroup_get() and cgroup_put()
Message-ID<qyupI-5Nu-11@gated-at.bofh.it>
In reply to#1276629
On Tue, Nov 24, 2015 at 11:30:56AM -0500, Tejun Heo wrote:
> Hello,
> 
> On Mon, Nov 16, 2015 at 01:51:41PM -0600, serge@hallyn.com wrote:
> > From: Aditya Kali <adityakali@google.com>
> > 
> > move cgroup_get() and cgroup_put() into cgroup.h so that
> > they can be called from other places.
> > 
> > Signed-off-by: Aditya Kali <adityakali@google.com>
> > Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
> > ---
> >  include/linux/cgroup.h |   21 +++++++++++++++++++++
> >  kernel/cgroup.c        |   22 ----------------------
> >  2 files changed, 21 insertions(+), 22 deletions(-)
> > 
> > diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
> > index 29f0b02..99096be 100644
> > --- a/include/linux/cgroup.h
> > +++ b/include/linux/cgroup.h
> > @@ -231,6 +231,27 @@ void css_task_iter_end(struct css_task_iter *it);
> >  #define css_for_each_descendant_post(pos, css)				\
> >  	for ((pos) = css_next_descendant_post(NULL, (css)); (pos);	\
> >  	     (pos) = css_next_descendant_post((pos), (css)))
> 
> Please insert a blank line here.
> 
> > +/* convenient tests for these bits */
> 
> And I don't think the comment makes sense here.
> 
> > +static inline bool cgroup_is_dead(const struct cgroup *cgrp)
> > +{
> > +	return !(cgrp->self.flags & CSS_ONLINE);
> > +}
> > +
> > +static inline void cgroup_get(struct cgroup *cgrp)
> > +{
> > +	WARN_ON_ONCE(cgroup_is_dead(cgrp));
> > +	css_get(&cgrp->self);
> > +}
> > +
> > +static inline bool cgroup_tryget(struct cgroup *cgrp)
> > +{
> > +	return css_tryget(&cgrp->self);
> > +}
> > +
> > +static inline void cgroup_put(struct cgroup *cgrp)
> > +{
> > +	css_put(&cgrp->self);
> > +}
> 
> So these are being exposed for cgroup NS support.  Hmmm... idk, does
> cgroup NS support needs to be in a spearate file?  The added amount
> isn't that big.  If we split cgroup.c, I'd much prefer to have
> cgroup-internal.h for internally shared stuff than pushing them out to
> cgroup.h.

Yeah, I think it makes more sense to merge them.

thanks,
-serge
--
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]


#1270535 — [PATCH 6/8] cgroup: cgroup namespace setns support

Fromserge@hallyn.com
Date2015-11-16 21:00 +0100
Subject[PATCH 6/8] cgroup: cgroup namespace setns support
Message-ID<qvy6v-3b3-29@gated-at.bofh.it>
In reply to#1270530
From: Aditya Kali <adityakali@google.com>

setns on a cgroup namespace is allowed only if
task has CAP_SYS_ADMIN in its current user-namespace and
over the user-namespace associated with target cgroupns.
No implicit cgroup changes happen with attaching to another
cgroupns. It is expected that the somone moves the attaching
process under the target cgroupns-root.

Signed-off-by: Aditya Kali <adityakali@google.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
---
 kernel/cgroup_namespace.c |   23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/kernel/cgroup_namespace.c b/kernel/cgroup_namespace.c
index ef20777..9651478 100644
--- a/kernel/cgroup_namespace.c
+++ b/kernel/cgroup_namespace.c
@@ -85,10 +85,27 @@ err_out:
 	return ERR_PTR(err);
 }
 
-static int cgroupns_install(struct nsproxy *nsproxy, void *ns)
+static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns) {
+	return container_of(ns, struct cgroup_namespace, ns);
+}
+
+static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns)
 {
-	pr_info("setns not supported for cgroup namespace");
-	return -EINVAL;
+	struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
+
+	if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) ||
+	    !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
+		return -EPERM;
+
+	/* Don't need to do anything if we are attaching to our own cgroupns. */
+	if (cgroup_ns == nsproxy->cgroup_ns)
+		return 0;
+
+	get_cgroup_ns(cgroup_ns);
+	put_cgroup_ns(nsproxy->cgroup_ns);
+	nsproxy->cgroup_ns = cgroup_ns;
+
+	return 0;
 }
 
 static struct ns_common *cgroupns_get(struct task_struct *task)
-- 
1.7.9.5

--
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]


#1276648 — Re: [PATCH 6/8] cgroup: cgroup namespace setns support

FromTejun Heo <tj@kernel.org>
Date2015-11-24 18:00 +0100
SubjectRe: [PATCH 6/8] cgroup: cgroup namespace setns support
Message-ID<qyp6F-2hl-1@gated-at.bofh.it>
In reply to#1270535
On Mon, Nov 16, 2015 at 01:51:43PM -0600, serge@hallyn.com wrote:
> @@ -85,10 +85,27 @@ err_out:
>  	return ERR_PTR(err);
>  }
>  
> -static int cgroupns_install(struct nsproxy *nsproxy, void *ns)
> +static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns) {
> +	return container_of(ns, struct cgroup_namespace, ns);
> +}

Heh, what's up with the formatting?  Please update the patches to
conform to Documentation/CodingStyle in general.

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]


#1270537 — [PATCH 1/8] kernfs: Add API to generate relative kernfs path

Fromserge@hallyn.com
Date2015-11-16 21:00 +0100
Subject[PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qvy6v-3b3-33@gated-at.bofh.it>
In reply to#1270530
From: Aditya Kali <adityakali@google.com>

The new function kernfs_path_from_node() generates and returns
kernfs path of a given kernfs_node relative to a given parent
kernfs_node.

Signed-off-by: Aditya Kali <adityakali@google.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
---
 fs/kernfs/dir.c        |  195 ++++++++++++++++++++++++++++++++++++++++++------
 include/linux/kernfs.h |    3 +
 2 files changed, 177 insertions(+), 21 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 91e0045..dba0d42 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -44,28 +44,159 @@ static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
 	return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
 }
 
-static char * __must_check kernfs_path_locked(struct kernfs_node *kn, char *buf,
-					      size_t buflen)
+/**
+ * kernfs_node_depth - compute depth of the kernfs node from root.
+ * The root node itself is considered to be at depth 0.
+ */
+static size_t kernfs_node_depth(struct kernfs_node *kn)
 {
-	char *p = buf + buflen;
+	size_t depth = 0;
+
+	BUG_ON(!kn);
+	while (kn->parent) {
+		depth++;
+		kn = kn->parent;
+	}
+	return depth;
+}
+
+/**
+ * kernfs_path_from_node_locked - find a relative path from @kn_from to @kn_to
+ * @kn_from: reference node of the path
+ * @kn_to: kernfs node to which path is needed
+ * @buf: buffer to copy the path into
+ * @buflen: size of @buf
+ *
+ * We need to handle couple of scenarios here:
+ * [1] when @kn_from is an ancestor of @kn_to at some level
+ * kn_from: /n1/n2/n3
+ * kn_to:   /n1/n2/n3/n4/n5
+ * result:  /n4/n5
+ *
+ * [2] when @kn_from is on a different hierarchy and we need to find common
+ * ancestor between @kn_from and @kn_to.
+ * kn_from: /n1/n2/n3/n4
+ * kn_to:   /n1/n2/n5
+ * result:  /../../n5
+ * OR
+ * kn_from: /n1/n2/n3/n4/n5   [depth=5]
+ * kn_to:   /n1/n2/n3         [depth=3]
+ * result:  /../..
+ */
+static char * __must_check kernfs_path_from_node_locked(
+	struct kernfs_node *kn_from,
+	struct kernfs_node *kn_to,
+	char *buf,
+	size_t buflen)
+{
+	char *p = buf;
+	struct kernfs_node *kn;
+	size_t depth_from = 0, depth_to, d;
 	int len;
 
-	*--p = '\0';
+	/* We atleast need 2 bytes to write "/\0". */
+	BUG_ON(buflen < 2);
 
-	do {
-		len = strlen(kn->name);
-		if (p - buf < len + 1) {
-			buf[0] = '\0';
-			p = NULL;
-			break;
+	/* Short-circuit the easy case - kn_to is the root node. */
+	if ((kn_from == kn_to) || (!kn_from && !kn_to->parent)) {
+		*p = '/';
+		*(p + 1) = '\0';
+		return p;
+	}
+
+	/* We can find the relative path only if both the nodes belong to the
+	 * same kernfs root.
+	 */
+	if (kn_from) {
+		BUG_ON(kernfs_root(kn_from) != kernfs_root(kn_to));
+		depth_from = kernfs_node_depth(kn_from);
+	}
+
+	depth_to = kernfs_node_depth(kn_to);
+
+	/* We compose path from left to right. So first write out all possible
+	 * "/.." strings needed to reach from 'kn_from' to the common ancestor.
+	 */
+	if (kn_from) {
+		while (depth_from > depth_to) {
+			len = strlen("/..");
+			if ((buflen - (p - buf)) < len + 1) {
+				/* buffer not big enough. */
+				buf[0] = '\0';
+				return NULL;
+			}
+			memcpy(p, "/..", len);
+			p += len;
+			*p = '\0';
+			--depth_from;
+			kn_from = kn_from->parent;
 		}
+
+		d = depth_to;
+		kn = kn_to;
+		while (depth_from < d) {
+			kn = kn->parent;
+			d--;
+		}
+
+		/* Now we have 'depth_from == depth_to' at this point. Add more
+		 * "/.."s until we reach common ancestor. In the worst case,
+		 * root node will be the common ancestor.
+		 */
+		while (depth_from > 0) {
+			/* If we reached common ancestor, stop. */
+			if (kn_from == kn)
+				break;
+			len = strlen("/..");
+			if ((buflen - (p - buf)) < len + 1) {
+				/* buffer not big enough. */
+				buf[0] = '\0';
+				return NULL;
+			}
+			memcpy(p, "/..", len);
+			p += len;
+			*p = '\0';
+			--depth_from;
+			kn_from = kn_from->parent;
+			kn = kn->parent;
+		}
+	}
+
+	/* Figure out how many bytes we need to write the path.
+	 */
+	d = depth_to;
+	kn = kn_to;
+	len = 0;
+	while (depth_from < d) {
+		/* Account for "/<name>". */
+		len += strlen(kn->name) + 1;
+		kn = kn->parent;
+		--d;
+	}
+
+	if ((buflen - (p - buf)) < len + 1) {
+		/* buffer not big enough. */
+		buf[0] = '\0';
+		return NULL;
+	}
+
+	/* We have enough space. Move 'p' ahead by computed length and start
+	 * writing node names into buffer.
+	 */
+	p += len;
+	*p = '\0';
+	d = depth_to;
+	kn = kn_to;
+	while (d > depth_from) {
+		len = strlen(kn->name);
 		p -= len;
 		memcpy(p, kn->name, len);
 		*--p = '/';
 		kn = kn->parent;
-	} while (kn && kn->parent);
+		--d;
+	}
 
-	return p;
+	return buf;
 }
 
 /**
@@ -115,26 +246,48 @@ size_t kernfs_path_len(struct kernfs_node *kn)
 }
 
 /**
- * kernfs_path - build full path of a given node
+ * kernfs_path_from_node - build path of node @kn relative to @kn_root.
+ * @kn_root: parent kernfs_node relative to which we need to build the path
  * @kn: kernfs_node of interest
- * @buf: buffer to copy @kn's name into
+ * @buf: buffer to copy @kn's path into
  * @buflen: size of @buf
  *
- * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
- * path is built from the end of @buf so the returned pointer usually
- * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
+ * Builds and returns @kn's path relative to @kn_root. @kn_root and @kn must
+ * be on the same kernfs-root. If @kn_root is not parent of @kn, then a relative
+ * path (which includes '..'s) as needed to reach from @kn_root to @kn is
+ * returned.
+ * The path may be built from the end of @buf so the returned pointer may not
+ * match @buf.  If @buf isn't long enough, @buf is nul terminated
  * and %NULL is returned.
  */
-char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
+char *kernfs_path_from_node(struct kernfs_node *kn_root, struct kernfs_node *kn,
+			    char *buf, size_t buflen)
 {
 	unsigned long flags;
 	char *p;
 
 	spin_lock_irqsave(&kernfs_rename_lock, flags);
-	p = kernfs_path_locked(kn, buf, buflen);
+	p = kernfs_path_from_node_locked(kn_root, kn, buf, buflen);
 	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
 	return p;
 }
+EXPORT_SYMBOL_GPL(kernfs_path_from_node);
+
+/**
+ * kernfs_path - build full path of a given node
+ * @kn: kernfs_node of interest
+ * @buf: buffer to copy @kn's name into
+ * @buflen: size of @buf
+ *
+ * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
+ * path is built from the end of @buf so the returned pointer usually
+ * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
+ * and %NULL is returned.
+ */
+char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
+{
+	return kernfs_path_from_node(NULL, kn, buf, buflen);
+}
 EXPORT_SYMBOL_GPL(kernfs_path);
 
 /**
@@ -168,8 +321,8 @@ void pr_cont_kernfs_path(struct kernfs_node *kn)
 
 	spin_lock_irqsave(&kernfs_rename_lock, flags);
 
-	p = kernfs_path_locked(kn, kernfs_pr_cont_buf,
-			       sizeof(kernfs_pr_cont_buf));
+	p = kernfs_path_from_node_locked(NULL, kn, kernfs_pr_cont_buf,
+					 sizeof(kernfs_pr_cont_buf));
 	if (p)
 		pr_cont("%s", p);
 	else
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 5d4e9c4..d025ebd 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -267,6 +267,9 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
 
 int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
 size_t kernfs_path_len(struct kernfs_node *kn);
+char * __must_check kernfs_path_from_node(struct kernfs_node *root_kn,
+					  struct kernfs_node *kn, char *buf,
+					  size_t buflen);
 char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
 				size_t buflen);
 void pr_cont_kernfs_name(struct kernfs_node *kn);
-- 
1.7.9.5

--
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]


#1276608 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

FromTejun Heo <tj@kernel.org>
Date2015-11-24 17:20 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qyotY-21n-19@gated-at.bofh.it>
In reply to#1270537
Oops, also please cc Greg Kroah-Hartman <gregkh@linuxfoundation.org>
on kernfs changes.

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]


#1276682 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

From"Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Date2015-11-24 18:50 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qypT4-2OB-3@gated-at.bofh.it>
In reply to#1276608
On Tue, Nov 24, 2015 at 11:17:09AM -0500, Tejun Heo wrote:
> Oops, also please cc Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> on kernfs changes.

Will do.  Thank you for all the feedback.  I'll send out a new set
when I get it all addressed.
--
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]


#1276609 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

FromTejun Heo <tj@kernel.org>
Date2015-11-24 17:20 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qyotY-21n-21@gated-at.bofh.it>
In reply to#1270537
Hello,

On Mon, Nov 16, 2015 at 01:51:38PM -0600, serge@hallyn.com wrote:
> +static char * __must_check kernfs_path_from_node_locked(
> +	struct kernfs_node *kn_from,
> +	struct kernfs_node *kn_to,
> +	char *buf,
> +	size_t buflen)
> +{
> +	char *p = buf;
> +	struct kernfs_node *kn;
> +	size_t depth_from = 0, depth_to, d;
>  	int len;
>  
> +	/* We atleast need 2 bytes to write "/\0". */
> +	BUG_ON(buflen < 2);

I don't think this is BUG worthy.  Just return NULL?  Also, the only
reason the original function returned char * was because the starting
point may not be the start of the buffer which helps keeping the
implementation simple.  If this function is gonna be complex anyway, a
better approach would be returning ssize_t and implement a simliar
behavior to strlcpy().

> +	/* Short-circuit the easy case - kn_to is the root node. */
> +	if ((kn_from == kn_to) || (!kn_from && !kn_to->parent)) {
> +		*p = '/';
> +		*(p + 1) = '\0';

Hmm... so if kn_from == kn_to, the output is "/"?

> +		return p;
> +	}
> +
> +	/* We can find the relative path only if both the nodes belong to the
> +	 * same kernfs root.
> +	 */
> +	if (kn_from) {
> +		BUG_ON(kernfs_root(kn_from) != kernfs_root(kn_to));

Ditto, just return NULL and maybe trigger WARN_ON_ONCE().

> +		depth_from = kernfs_node_depth(kn_from);
> +	}
> +
> +	depth_to = kernfs_node_depth(kn_to);
> +
> +	/* We compose path from left to right. So first write out all possible
                                             ^
					     , so

> +	 * "/.." strings needed to reach from 'kn_from' to the common ancestor.
> +	 */

Please fully-wing multiline comments.

> +	if (kn_from) {
> +		while (depth_from > depth_to) {
> +			len = strlen("/..");

Maybe do something like the following instead?

			const char parent_str[] = "/..";
			size_t len = sizeof(parent_str) - 1;

> +			if ((buflen - (p - buf)) < len + 1) {
> +				/* buffer not big enough. */
> +				buf[0] = '\0';
> +				return NULL;
> +			}
> +			memcpy(p, "/..", len);
> +			p += len;
> +			*p = '\0';
> +			--depth_from;
> +			kn_from = kn_from->parent;
>  		}
> +
> +		d = depth_to;
> +		kn = kn_to;
> +		while (depth_from < d) {
> +			kn = kn->parent;
> +			d--;
> +		}
> +
> +		/* Now we have 'depth_from == depth_to' at this point. Add more

Ditto with winging.

> +		 * "/.."s until we reach common ancestor. In the worst case,
> +		 * root node will be the common ancestor.
> +		 */
> +		while (depth_from > 0) {
> +			/* If we reached common ancestor, stop. */
> +			if (kn_from == kn)
> +				break;
> +			len = strlen("/..");
> +			if ((buflen - (p - buf)) < len + 1) {
> +				/* buffer not big enough. */
> +				buf[0] = '\0';
> +				return NULL;
> +			}
> +			memcpy(p, "/..", len);
> +			p += len;
> +			*p = '\0';
> +			--depth_from;
> +			kn_from = kn_from->parent;
> +			kn = kn->parent;
> +		}

Hmmm... I wonder whether this and the above block can be merged.
Wouldn't it be simpler to calculate common ancestor and generate
/.. till it reached that point?

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]


#1278543 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

From"Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Date2015-11-27 06:30 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qzjLA-6YF-11@gated-at.bofh.it>
In reply to#1276609
On Tue, Nov 24, 2015 at 11:16:30AM -0500, Tejun Heo wrote:
> Hello,
> 
> On Mon, Nov 16, 2015 at 01:51:38PM -0600, serge@hallyn.com wrote:
> > +static char * __must_check kernfs_path_from_node_locked(

(Note I've rewritten this to find a common ancestor and walk back to
and from that, as you suggested later in this email)

> > +	/* Short-circuit the easy case - kn_to is the root node. */
> > +	if ((kn_from == kn_to) || (!kn_from && !kn_to->parent)) {
> > +		*p = '/';
> > +		*(p + 1) = '\0';
> 
> Hmm... so if kn_from == kn_to, the output is "/"?

Yes, that's what seems to make the most sense for cgroup namespaces.  I
could see a case for '.' being used instead in general, but for cgroup
namespaces I think we'd have to convert those back to '/'.  Otherwise
we'll fail in being able to run legacy software, which would get
confused.

-serge
--
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]


#1279982 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

FromTejun Heo <tj@kernel.org>
Date2015-11-30 16:20 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qAypd-5id-41@gated-at.bofh.it>
In reply to#1278543
Hello,

On Thu, Nov 26, 2015 at 11:25:11PM -0600, Serge E. Hallyn wrote:
> > > +	/* Short-circuit the easy case - kn_to is the root node. */
> > > +	if ((kn_from == kn_to) || (!kn_from && !kn_to->parent)) {
> > > +		*p = '/';
> > > +		*(p + 1) = '\0';
> > 
> > Hmm... so if kn_from == kn_to, the output is "/"?
> 
> Yes, that's what seems to make the most sense for cgroup namespaces.  I
> could see a case for '.' being used instead in general, but for cgroup
> namespaces I think we'd have to convert those back to '/'.  Otherwise
> we'll fail in being able to run legacy software, which would get
> confused.

Yeah, I agree but the name is kinda misleading tho.  The output isn't
really a relative path but rather absolute path against the specified
root.  Maybe updating the function and parameter names would be
helpful?

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]


#1280187 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

From"Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Date2015-11-30 19:40 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qABwL-7d9-37@gated-at.bofh.it>
In reply to#1279982
On Mon, Nov 30, 2015 at 10:11:47AM -0500, Tejun Heo wrote:
> Hello,
> 
> On Thu, Nov 26, 2015 at 11:25:11PM -0600, Serge E. Hallyn wrote:
> > > > +	/* Short-circuit the easy case - kn_to is the root node. */
> > > > +	if ((kn_from == kn_to) || (!kn_from && !kn_to->parent)) {
> > > > +		*p = '/';
> > > > +		*(p + 1) = '\0';
> > > 
> > > Hmm... so if kn_from == kn_to, the output is "/"?
> > 
> > Yes, that's what seems to make the most sense for cgroup namespaces.  I
> > could see a case for '.' being used instead in general, but for cgroup
> > namespaces I think we'd have to convert those back to '/'.  Otherwise
> > we'll fail in being able to run legacy software, which would get
> > confused.
> 
> Yeah, I agree but the name is kinda misleading tho.  The output isn't
> really a relative path but rather absolute path against the specified
> root.  Maybe updating the function and parameter names would be
> helpful?
> 
> Thanks.

Ok - updating the comment is simple enough.  Though the name/params
kernfs_path_from_node_locked(from, to) still seem to make sense.  Would
you prefer something like kernfs_absolute_path_from node_locked()?  I
hesitate to call 'from' 'root' since kernfs_root is a thing and this
is not that.

--
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]


#1280385 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

FromTejun Heo <tj@kernel.org>
Date2015-12-01 00:00 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qAFAl-1gu-1@gated-at.bofh.it>
In reply to#1280187
Hello, Serge.

On Mon, Nov 30, 2015 at 12:37:58PM -0600, Serge E. Hallyn wrote:
> > Yeah, I agree but the name is kinda misleading tho.  The output isn't
> > really a relative path but rather absolute path against the specified
> > root.  Maybe updating the function and parameter names would be
> > helpful?
> > 
> 
> Ok - updating the comment is simple enough.  Though the name/params
> kernfs_path_from_node_locked(from, to) still seem to make sense.  Would
> you prefer something like kernfs_absolute_path_from node_locked()?  I
> hesitate to call 'from' 'root' since kernfs_root is a thing and this
> is not that.

Hmmm... I see.  Let's just make sure that the comment is clear about
the fact that it calculates (pseudo) absolute path rather than
relative path.

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]


#1280496 — Re: [PATCH 1/8] kernfs: Add API to generate relative kernfs path

From"Serge E. Hallyn" <serge.hallyn@ubuntu.com>
Date2015-12-01 03:10 +0100
SubjectRe: [PATCH 1/8] kernfs: Add API to generate relative kernfs path
Message-ID<qAIyd-3oM-5@gated-at.bofh.it>
In reply to#1280385
On Mon, Nov 30, 2015 at 05:53:18PM -0500, Tejun Heo wrote:
> Hello, Serge.
> 
> On Mon, Nov 30, 2015 at 12:37:58PM -0600, Serge E. Hallyn wrote:
> > > Yeah, I agree but the name is kinda misleading tho.  The output isn't
> > > really a relative path but rather absolute path against the specified
> > > root.  Maybe updating the function and parameter names would be
> > > helpful?
> > > 
> > 
> > Ok - updating the comment is simple enough.  Though the name/params
> > kernfs_path_from_node_locked(from, to) still seem to make sense.  Would
> > you prefer something like kernfs_absolute_path_from node_locked()?  I
> > hesitate to call 'from' 'root' since kernfs_root is a thing and this
> > is not that.
> 
> Hmmm... I see.  Let's just make sure that the comment is clear about
> the fact that it calculates (pseudo) absolute path rather than
> relative path.
> 
> Thanks.

Ok, new patch follows (and is pushed at
 https://git.kernel.org/cgit/linux/kernel/git/sergeh/linux-security.git/log/?h=2015-11-30/cgroupns)

[PATCH 1/7] kernfs: Add API to generate relative kernfs path

The new function kernfs_path_from_node() generates and returns kernfs
path of a given kernfs_node relative to a given parent kernfs_node.

Changelog 20151125:
  - Fully-wing multilinecomments
  - Rework kernfs_path_from_node_locked() logic
  - Replace BUG_ONs with returning NULL
  - Use a const char* for /.. and precalculate its size
Changelog 20151130:
  - Update kernfs_path_from_node_locked comment

Signed-off-by: Aditya Kali <adityakali@google.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
---
 fs/kernfs/dir.c        | 182 +++++++++++++++++++++++++++++++++++++++++--------
 include/linux/kernfs.h |   3 +
 2 files changed, 158 insertions(+), 27 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 91e0045..7cd4bb4 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -44,28 +44,134 @@ static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen)
 	return strlcpy(buf, kn->parent ? kn->name : "/", buflen);
 }
 
-static char * __must_check kernfs_path_locked(struct kernfs_node *kn, char *buf,
-					      size_t buflen)
+/* kernfs_node_depth - compute depth from @from to @to */
+static size_t kernfs_node_distance(struct kernfs_node *from, struct kernfs_node *to)
 {
-	char *p = buf + buflen;
-	int len;
+	size_t depth = 0;
 
-	*--p = '\0';
+	BUG_ON(!to);
+	BUG_ON(!from);
 
-	do {
-		len = strlen(kn->name);
-		if (p - buf < len + 1) {
-			buf[0] = '\0';
-			p = NULL;
-			break;
-		}
-		p -= len;
-		memcpy(p, kn->name, len);
-		*--p = '/';
-		kn = kn->parent;
-	} while (kn && kn->parent);
+	while (to->parent && to != from) {
+		depth++;
+		to = to->parent;
+	}
+	return depth;
+}
 
-	return p;
+static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
+		struct kernfs_node *b)
+{
+	size_t da = kernfs_node_distance(kernfs_root(a)->kn, a);
+	size_t db = kernfs_node_distance(kernfs_root(b)->kn, b);
+
+	if (da == 0)
+		return a;
+	if (db == 0)
+		return b;
+
+	while (da > db) {
+		a = a->parent;
+		da--;
+	}
+	while (db > da) {
+		b = b->parent;
+		db--;
+	}
+
+	/* worst case b and a will be the same at root */
+	while (b != a) {
+		b = b->parent;
+		a = a->parent;
+	}
+
+	return a;
+}
+
+/**
+ * kernfs_path_from_node_locked - find a pseudo-absolute path to @kn_to,
+ * where kn_from is treated as root of the path.
+ * @kn_from: kernfs node which should be treated as root for the path
+ * @kn_to: kernfs node to which path is needed
+ * @buf: buffer to copy the path into
+ * @buflen: size of @buf
+ *
+ * We need to handle couple of scenarios here:
+ * [1] when @kn_from is an ancestor of @kn_to at some level
+ * kn_from: /n1/n2/n3
+ * kn_to:   /n1/n2/n3/n4/n5
+ * result:  /n4/n5
+ *
+ * [2] when @kn_from is on a different hierarchy and we need to find common
+ * ancestor between @kn_from and @kn_to.
+ * kn_from: /n1/n2/n3/n4
+ * kn_to:   /n1/n2/n5
+ * result:  /../../n5
+ * OR
+ * kn_from: /n1/n2/n3/n4/n5   [depth=5]
+ * kn_to:   /n1/n2/n3         [depth=3]
+ * result:  /../..
+ */
+static char *
+__must_check kernfs_path_from_node_locked(struct kernfs_node *kn_from,
+					  struct kernfs_node *kn_to, char *buf,
+					  size_t buflen)
+{
+	char *p = buf;
+	struct kernfs_node *kn, *common;
+	const char parent_str[] = "/..";
+	int i;
+	size_t depth_from, depth_to, len = 0, nlen = 0,
+	       plen = sizeof(parent_str) - 1;
+
+	/* We atleast need 2 bytes to write "/\0". */
+	if (buflen < 2)
+		return NULL;
+
+	if (!kn_from)
+		kn_from = kernfs_root(kn_to)->kn;
+
+	if (kn_from == kn_to) {
+		*p = '/';
+		*(++p) = '\0';
+		return buf;
+	}
+
+	common = kernfs_common_ancestor(kn_from, kn_to);
+	if (!common) {
+		WARN_ONCE("%s: kn_from and kn_to on different roots\n",
+			__func__);
+		return NULL;
+	}
+
+	depth_to = kernfs_node_distance(common, kn_to);
+	depth_from = kernfs_node_distance(common, kn_from);
+
+	for (i = 0; i < depth_from; i++) {
+		if (len + plen + 1 > buflen)
+			return NULL;
+		strcpy(p, parent_str);
+		p += plen;
+		len += plen;
+	}
+
+	/* Calculate how many bytes we need for the rest */
+	for (kn = kn_to; kn != common; kn = kn->parent)
+		nlen += strlen(kn->name) + 1;
+
+	if (len + nlen + 1 > buflen)
+		return NULL;
+
+	p += nlen;
+	*p = '\0';
+	for (kn = kn_to; kn != common; kn = kn->parent) {
+		nlen = strlen(kn->name);
+		p -= nlen;
+		memcpy(p, kn->name, nlen);
+		*(--p) = '/';
+	}
+
+	return buf;
 }
 
 /**
@@ -115,26 +221,48 @@ size_t kernfs_path_len(struct kernfs_node *kn)
 }
 
 /**
- * kernfs_path - build full path of a given node
+ * kernfs_path_from_node - build path of node @kn relative to @kn_root.
+ * @kn_root: parent kernfs_node relative to which we need to build the path
  * @kn: kernfs_node of interest
- * @buf: buffer to copy @kn's name into
+ * @buf: buffer to copy @kn's path into
  * @buflen: size of @buf
  *
- * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
- * path is built from the end of @buf so the returned pointer usually
- * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
+ * Builds and returns @kn's path relative to @kn_root. @kn_root and @kn must
+ * be on the same kernfs-root. If @kn_root is not parent of @kn, then a relative
+ * path (which includes '..'s) as needed to reach from @kn_root to @kn is
+ * returned.
+ * The path may be built from the end of @buf so the returned pointer may not
+ * match @buf.  If @buf isn't long enough, @buf is nul terminated
  * and %NULL is returned.
  */
-char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
+char *kernfs_path_from_node(struct kernfs_node *kn_root, struct kernfs_node *kn,
+			    char *buf, size_t buflen)
 {
 	unsigned long flags;
 	char *p;
 
 	spin_lock_irqsave(&kernfs_rename_lock, flags);
-	p = kernfs_path_locked(kn, buf, buflen);
+	p = kernfs_path_from_node_locked(kn_root, kn, buf, buflen);
 	spin_unlock_irqrestore(&kernfs_rename_lock, flags);
 	return p;
 }
+EXPORT_SYMBOL_GPL(kernfs_path_from_node);
+
+/**
+ * kernfs_path - build full path of a given node
+ * @kn: kernfs_node of interest
+ * @buf: buffer to copy @kn's name into
+ * @buflen: size of @buf
+ *
+ * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
+ * path is built from the end of @buf so the returned pointer usually
+ * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
+ * and %NULL is returned.
+ */
+char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
+{
+	return kernfs_path_from_node(NULL, kn, buf, buflen);
+}
 EXPORT_SYMBOL_GPL(kernfs_path);
 
 /**
@@ -168,8 +296,8 @@ void pr_cont_kernfs_path(struct kernfs_node *kn)
 
 	spin_lock_irqsave(&kernfs_rename_lock, flags);
 
-	p = kernfs_path_locked(kn, kernfs_pr_cont_buf,
-			       sizeof(kernfs_pr_cont_buf));
+	p = kernfs_path_from_node_locked(NULL, kn, kernfs_pr_cont_buf,
+					 sizeof(kernfs_pr_cont_buf));
 	if (p)
 		pr_cont("%s", p);
 	else
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 5d4e9c4..d025ebd 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -267,6 +267,9 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn)
 
 int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen);
 size_t kernfs_path_len(struct kernfs_node *kn);
+char * __must_check kernfs_path_from_node(struct kernfs_node *root_kn,
+					  struct kernfs_node *kn, char *buf,
+					  size_t buflen);
 char * __must_check kernfs_path(struct kernfs_node *kn, char *buf,
 				size_t buflen);
 void pr_cont_kernfs_name(struct kernfs_node *kn);
-- 
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]


#1270565

From"Serge E. Hallyn" <serge@hallyn.com>
Date2015-11-16 21:50 +0100
Message-ID<qvySR-3Je-11@gated-at.bofh.it>
In reply to#1270530
On Mon, Nov 16, 2015 at 09:41:15PM +0100, Richard Weinberger wrote:
> Serge,
> 
> On Mon, Nov 16, 2015 at 8:51 PM,  <serge@hallyn.com> wrote:
> > To summarize the semantics:
> >
> > 1. CLONE_NEWCGROUP re-uses 0x02000000, which was previously CLONE_STOPPED
> >
> > 2. unsharing a cgroup namespace makes all your current cgroups your new
> > cgroup root.
> >
> > 3. /proc/pid/cgroup always shows cgroup paths relative to the reader's
> > cgroup namespce root.  A task outside of  your cgroup looks like
> >
> >         8:memory:/../../..
> >
> > 4. when a task mounts a cgroupfs, the cgroup which shows up as root depends
> > on the mounting task's  cgroup namespace.
> >
> > 5. setns to a cgroup namespace switches your cgroup namespace but not
> > your cgroups.
> >
> > With this, using github.com/hallyn/lxc #2015-11-09/cgns (and
> > github.com/hallyn/lxcfs #2015-11-10/cgns) we can start a container in a full
> > proper cgroup namespace, avoiding either cgmanager or lxcfs cgroup bind mounts.
> >
> > This is completely backward compatible and will be completely invisible
> > to any existing cgroup users (except for those running inside a cgroup
> > namespace and looking at /proc/pid/cgroup of tasks outside their
> > namespace.)
> >    cgroupns-root.
> 
> IIRC one downside of this series was that only the new "sane" cgroup
> layout was supported
> and hence it was useless for everything which expected the default layout.
> Hence, still no systemd for us. :)
> 
> Is this now different?

Yes, all hierachies are no supported.
--
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]


#1270571

FromRichard Weinberger <richard@nod.at>
Date2015-11-16 22:00 +0100
Message-ID<qvz2y-3Mz-13@gated-at.bofh.it>
In reply to#1270565
Am 16.11.2015 um 21:46 schrieb Serge E. Hallyn:
> On Mon, Nov 16, 2015 at 09:41:15PM +0100, Richard Weinberger wrote:
>> Serge,
>>
>> On Mon, Nov 16, 2015 at 8:51 PM,  <serge@hallyn.com> wrote:
>>> To summarize the semantics:
>>>
>>> 1. CLONE_NEWCGROUP re-uses 0x02000000, which was previously CLONE_STOPPED
>>>
>>> 2. unsharing a cgroup namespace makes all your current cgroups your new
>>> cgroup root.
>>>
>>> 3. /proc/pid/cgroup always shows cgroup paths relative to the reader's
>>> cgroup namespce root.  A task outside of  your cgroup looks like
>>>
>>>         8:memory:/../../..
>>>
>>> 4. when a task mounts a cgroupfs, the cgroup which shows up as root depends
>>> on the mounting task's  cgroup namespace.
>>>
>>> 5. setns to a cgroup namespace switches your cgroup namespace but not
>>> your cgroups.
>>>
>>> With this, using github.com/hallyn/lxc #2015-11-09/cgns (and
>>> github.com/hallyn/lxcfs #2015-11-10/cgns) we can start a container in a full
>>> proper cgroup namespace, avoiding either cgmanager or lxcfs cgroup bind mounts.
>>>
>>> This is completely backward compatible and will be completely invisible
>>> to any existing cgroup users (except for those running inside a cgroup
>>> namespace and looking at /proc/pid/cgroup of tasks outside their
>>> namespace.)
>>>    cgroupns-root.
>>
>> IIRC one downside of this series was that only the new "sane" cgroup
>> layout was supported
>> and hence it was useless for everything which expected the default layout.
>> Hence, still no systemd for us. :)
>>
>> Is this now different?
> 
> Yes, all hierachies are no supported.
> 

Should read "now"? :-)
If so, *awesome*!

Thanks,
//richard
--
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]


#1270575

From"Serge E. Hallyn" <serge@hallyn.com>
Date2015-11-16 22:00 +0100
Message-ID<qvz2y-3Mz-17@gated-at.bofh.it>
In reply to#1270571
On Mon, Nov 16, 2015 at 09:50:55PM +0100, Richard Weinberger wrote:
> Am 16.11.2015 um 21:46 schrieb Serge E. Hallyn:
> > On Mon, Nov 16, 2015 at 09:41:15PM +0100, Richard Weinberger wrote:
> >> Serge,
> >>
> >> On Mon, Nov 16, 2015 at 8:51 PM,  <serge@hallyn.com> wrote:
> >>> To summarize the semantics:
> >>>
> >>> 1. CLONE_NEWCGROUP re-uses 0x02000000, which was previously CLONE_STOPPED
> >>>
> >>> 2. unsharing a cgroup namespace makes all your current cgroups your new
> >>> cgroup root.
> >>>
> >>> 3. /proc/pid/cgroup always shows cgroup paths relative to the reader's
> >>> cgroup namespce root.  A task outside of  your cgroup looks like
> >>>
> >>>         8:memory:/../../..
> >>>
> >>> 4. when a task mounts a cgroupfs, the cgroup which shows up as root depends
> >>> on the mounting task's  cgroup namespace.
> >>>
> >>> 5. setns to a cgroup namespace switches your cgroup namespace but not
> >>> your cgroups.
> >>>
> >>> With this, using github.com/hallyn/lxc #2015-11-09/cgns (and
> >>> github.com/hallyn/lxcfs #2015-11-10/cgns) we can start a container in a full
> >>> proper cgroup namespace, avoiding either cgmanager or lxcfs cgroup bind mounts.
> >>>
> >>> This is completely backward compatible and will be completely invisible
> >>> to any existing cgroup users (except for those running inside a cgroup
> >>> namespace and looking at /proc/pid/cgroup of tasks outside their
> >>> namespace.)
> >>>    cgroupns-root.
> >>
> >> IIRC one downside of this series was that only the new "sane" cgroup
> >> layout was supported
> >> and hence it was useless for everything which expected the default layout.
> >> Hence, still no systemd for us. :)
> >>
> >> Is this now different?
> > 
> > Yes, all hierachies are no supported.
> > 
> 
> Should read "now"? :-)
> If so, *awesome*!

D'oh!  Yes, now :-)

-serge
--
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]


#1270657

Fromebiederm@xmission.com (Eric W. Biederman)
Date2015-11-16 23:40 +0100
Message-ID<qvABj-4Q6-11@gated-at.bofh.it>
In reply to#1270575
"Serge E. Hallyn" <serge@hallyn.com> writes:

> On Mon, Nov 16, 2015 at 09:50:55PM +0100, Richard Weinberger wrote:
>> Am 16.11.2015 um 21:46 schrieb Serge E. Hallyn:
>> > On Mon, Nov 16, 2015 at 09:41:15PM +0100, Richard Weinberger wrote:
>> >> Serge,
>> >>
>> >> On Mon, Nov 16, 2015 at 8:51 PM,  <serge@hallyn.com> wrote:
>> >>> To summarize the semantics:
>> >>>
>> >>> 1. CLONE_NEWCGROUP re-uses 0x02000000, which was previously CLONE_STOPPED
>> >>>
>> >>> 2. unsharing a cgroup namespace makes all your current cgroups your new
>> >>> cgroup root.
>> >>>
>> >>> 3. /proc/pid/cgroup always shows cgroup paths relative to the reader's
>> >>> cgroup namespce root.  A task outside of  your cgroup looks like
>> >>>
>> >>>         8:memory:/../../..
>> >>>
>> >>> 4. when a task mounts a cgroupfs, the cgroup which shows up as root depends
>> >>> on the mounting task's  cgroup namespace.
>> >>>
>> >>> 5. setns to a cgroup namespace switches your cgroup namespace but not
>> >>> your cgroups.
>> >>>
>> >>> With this, using github.com/hallyn/lxc #2015-11-09/cgns (and
>> >>> github.com/hallyn/lxcfs #2015-11-10/cgns) we can start a container in a full
>> >>> proper cgroup namespace, avoiding either cgmanager or lxcfs cgroup bind mounts.
>> >>>
>> >>> This is completely backward compatible and will be completely invisible
>> >>> to any existing cgroup users (except for those running inside a cgroup
>> >>> namespace and looking at /proc/pid/cgroup of tasks outside their
>> >>> namespace.)
>> >>>    cgroupns-root.
>> >>
>> >> IIRC one downside of this series was that only the new "sane" cgroup
>> >> layout was supported
>> >> and hence it was useless for everything which expected the default layout.
>> >> Hence, still no systemd for us. :)
>> >>
>> >> Is this now different?
>> > 
>> > Yes, all hierachies are no supported.
>> > 
>> 
>> Should read "now"? :-)
>> If so, *awesome*!
>
> D'oh!  Yes, now :-)

I am glad to see multiple hierarchy support, that is something people
can use today.

A couple of quick questions before I delve into a review.

Does this allow mixing of cgroupfs and cgroupfs2?  That is can I: "mount
-t cgroupfs" inside a container and "mount -t cgroupfs2" outside a
container? and still have reasonable things happen?  I suspect the
semantics of cgroups prevent this but I am interested to know what happens.

Similary have you considered what it required to be able to safely set
FS_USERNS_MOUNT?

Eric
--
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]


#1270660

FromTejun Heo <tj@kernel.org>
Date2015-11-16 23:40 +0100
Message-ID<qvABk-4Q6-25@gated-at.bofh.it>
In reply to#1270657
Hello, Eric.

On Mon, Nov 16, 2015 at 04:24:27PM -0600, Eric W. Biederman wrote:
> Does this allow mixing of cgroupfs and cgroupfs2?  That is can I: "mount
> -t cgroupfs" inside a container and "mount -t cgroupfs2" outside a
> container? and still have reasonable things happen?  I suspect the
> semantics of cgroups prevent this but I am interested to know what happens.

cgroup v1 and v2 are just separate hierarchies.  They can't nest each
other but co-existing and namespacing on their own is completely fine.
The caveat is that a given controller can be on only one hierarchy but
that's the same among v1 hierarchies too.

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]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web