lkml.org 
[lkml]   [2015]   [Dec]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 7/8] cgroup: mount cgroupns-root when inside non-init cgroupns
    On Wed, Dec 02, 2015 at 12:05:51PM -0500, Tejun Heo wrote:
    > On Wed, Dec 02, 2015 at 11:02:39AM -0600, Serge E. Hallyn wrote:
    > > On Wed, Dec 02, 2015 at 11:58:39AM -0500, Tejun Heo wrote:
    > > > On Wed, Dec 02, 2015 at 10:56:37AM -0600, Serge E. Hallyn wrote:
    > > > > Can it be flushed when we know that the cgroup is being pinned by
    > > > > a css_set? (There's either a task or a cgroup_namespace pinning it
    > > > > or we wouldn't get here)
    > > >
    > > > Yeap, it can be flushed. There's no ref coming out of cgroup to the
    > > > vfs objects.
    > >
    > > Ok, thanks. Still seems to me to be more work to actually walk the
    > > path ourselves, but I'll go that route and see what it looks like :)
    >
    > I just dislike having two separate paths instantiating the same
    > objects and would prefer doing it the same way userland would do if
    > that isn't too complex but yeah it might turn out to be a lot more
    > work.
    >
    > Thanks a lot!

    Here's a patch to make that change. Seems to be working for me. If it
    looks ok I can fold it into the prevoius patches and resend the new set.

    PATCH 1/1] kernfs_obtain_root: switch to walking the path [fold up]

    Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
    ---
    fs/kernfs/mount.c | 80 ++++++++++++++++++++++++++++++++-----------------------
    1 file changed, 47 insertions(+), 33 deletions(-)

    diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
    index cc41fe1..027f4ca 100644
    --- a/fs/kernfs/mount.c
    +++ b/fs/kernfs/mount.c
    @@ -14,6 +14,7 @@
    #include <linux/magic.h>
    #include <linux/slab.h>
    #include <linux/pagemap.h>
    +#include <linux/namei.h>

    #include "kernfs-internal.h"

    @@ -62,6 +63,27 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
    return NULL;
    }

    +/*
    + * find the next ancestor in the path down to @child, where @parent was the
    + * parent whose child we want to find.
    + *
    + * Say the path is /a/b/c/d. @child is d, @parent is NULL. We return the root
    + * node. If @parent is b, then we return the node for c.
    + * Passing in d as @parent is not ok.
    + */
    +static struct kernfs_node *
    +find_kn_ancestor_below(struct kernfs_node *child, struct kernfs_node *parent)
    +{
    + BUG_ON(child == parent);
    +
    + while (child->parent != parent) {
    + BUG_ON(!child->parent);
    + child = child->parent;
    + }
    +
    + return child;
    +}
    +
    /**
    * kernfs_obtain_root - get a dentry for the given kernfs_node
    * @sb: the kernfs super_block
    @@ -74,42 +96,34 @@ struct dentry *kernfs_obtain_root(struct super_block *sb,
    struct kernfs_node *kn)
    {
    struct dentry *dentry;
    - struct inode *inode;
    + struct kernfs_node *knparent = NULL;

    BUG_ON(sb->s_op != &kernfs_sops);

    - /* inode for the given kernfs_node should already exist. */
    - inode = kernfs_get_inode(sb, kn);
    - if (!inode) {
    - pr_debug("kernfs: could not get inode for '");
    - pr_cont_kernfs_path(kn);
    - pr_cont("'.\n");
    - return ERR_PTR(-EINVAL);
    - }
    -
    - /* instantiate and link root dentry */
    - dentry = d_obtain_root(inode);
    - if (!dentry) {
    - pr_debug("kernfs: could not get dentry for '");
    - pr_cont_kernfs_path(kn);
    - pr_cont("'.\n");
    - return ERR_PTR(-ENOMEM);
    - }
    -
    - /*
    - * If this is a new dentry, set it up. We need kernfs_mutex because
    - * this may be called by callers other than kernfs_fill_super.
    - */
    - mutex_lock(&kernfs_mutex);
    - if (!dentry->d_fsdata) {
    - kernfs_get(kn);
    - dentry->d_fsdata = kn;
    - } else {
    - WARN_ON(dentry->d_fsdata != kn);
    - }
    - mutex_unlock(&kernfs_mutex);
    -
    - return dentry;
    + dentry = dget(sb->s_root);
    + if (!kn->parent) // this is the root
    + return dentry;
    +
    + knparent = find_kn_ancestor_below(kn, NULL);
    + BUG_ON(!knparent);
    +
    + do {
    + struct dentry *dtmp;
    + struct kernfs_node *kntmp;
    +
    + if (kn == knparent)
    + return dentry;
    + kntmp = find_kn_ancestor_below(kn, knparent);
    + BUG_ON(!kntmp);
    + dtmp = lookup_one_len(kntmp->name, dentry, strlen(kntmp->name));
    + dput(dentry);
    + if (IS_ERR(dtmp))
    + return dtmp;
    + knparent = kntmp;
    + dentry = dtmp;
    + } while (1);
    +
    + // notreached
    }

    static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
    --
    2.5.0


    \
     
     \ /
      Last update: 2015-12-04 00:21    [W:3.691 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site