lkml.org 
[lkml]   [2017]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    SubjectRe: [RFC 1/1] shiftfs: uid/gid shifting bind mount
    From
    Date
    On Fri, 2017-02-17 at 02:29 +0000, Al Viro wrote:
    > On Sat, Feb 04, 2017 at 11:19:32AM -0800, James Bottomley wrote:
    >
    > > +static const struct dentry_operations shiftfs_dentry_ops = {
    > > + .d_release = shiftfs_d_release,
    > > + .d_real = shiftfs_d_real,
    > > +};
    >
    > In other words, those dentries are *never* revalidated. Nevermind
    > that underlying fs might be mounted elsewhere and be actively
    > modified under you.
    >
    > > +static struct dentry *shiftfs_lookup(struct inode *dir, struct
    > > dentry *dentry,
    > > + unsigned int flags)
    > > +{
    > > + struct dentry *real = dir->i_private, *new;
    > > + struct inode *reali = real->d_inode, *newi;
    > > + const struct cred *oldcred, *newcred;
    > > +
    > > + inode_lock(reali);
    > > + oldcred = shiftfs_new_creds(&newcred, dentry->d_sb);
    > > + new = lookup_one_len(dentry->d_name.name, real, dentry
    > > ->d_name.len);
    > > + shiftfs_old_creds(oldcred, &newcred);
    > > + inode_unlock(reali);
    > > +
    > > + if (IS_ERR(new))
    > > + return new;
    > > +
    > > + dentry->d_fsdata = new;
    > > +
    > > + if (!new->d_inode)
    > > + return NULL;
    >
    > What happens when somebody comes along and creates the damn thing on
    > the underlying fs? _Not_ via your code, that is - using the
    > underlying fs mounted elsewhere.

    Point taken. This, I think fixes the dcache revalidation issue.

    James

    ---

    diff --git a/fs/shiftfs.c b/fs/shiftfs.c
    index a4a1f98..1e71efe 100644
    --- a/fs/shiftfs.c
    +++ b/fs/shiftfs.c
    @@ -118,9 +118,43 @@ static struct dentry *shiftfs_d_real(struct dentry *dentry,
    return real;
    }

    +static int shiftfs_d_weak_revalidate(struct dentry *dentry, unsigned int flags)
    +{
    + struct dentry *real = dentry->d_fsdata;
    +
    + if (d_unhashed(real))
    + return 0;
    +
    + if (!(real->d_flags & DCACHE_OP_WEAK_REVALIDATE))
    + return 1;
    +
    + return real->d_op->d_weak_revalidate(real, flags);
    +}
    +
    +static int shiftfs_d_revalidate(struct dentry *dentry, unsigned int flags)
    +{
    + struct dentry *real = dentry->d_fsdata;
    + int ret;
    +
    + if (d_unhashed(real))
    + return 0;
    +
    + if (!(real->d_flags & DCACHE_OP_REVALIDATE))
    + return 1;
    +
    + ret = real->d_op->d_revalidate(real, flags);
    +
    + if (ret == 0 && !(flags & LOOKUP_RCU))
    + d_invalidate(real);
    +
    + return ret;
    +}
    +
    static const struct dentry_operations shiftfs_dentry_ops = {
    .d_release = shiftfs_d_release,
    .d_real = shiftfs_d_real,
    + .d_revalidate = shiftfs_d_revalidate,
    + .d_weak_revalidate = shiftfs_d_weak_revalidate,
    };

    static int shiftfs_readlink(struct dentry *dentry, char __user *data,
    @@ -431,9 +465,7 @@ static struct dentry *shiftfs_lookup(struct inode *dir, struct dentry *dentry,
    return ERR_PTR(-ENOMEM);
    }

    - d_splice_alias(newi, dentry);
    -
    - return NULL;
    + return d_splice_alias(newi, dentry);
    }

    static int shiftfs_permission(struct inode *inode, int mask)
    \
     
     \ /
      Last update: 2017-02-17 18:25    [W:4.213 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site