lkml.org 
[lkml]   [2007]   [Sep]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 22/32] Unionfs: handling lower vfsmount fixes
    Date
    From: Erez Zadok <ezk@cs.sunysb.edu>

    Properly increase/release lower vfsmounts.
    Validate proper use of unionfs mntget/put.

    Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
    Signed-off-by: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
    ---
    fs/unionfs/dentry.c | 6 ++++--
    fs/unionfs/inode.c | 11 +++++++++++
    fs/unionfs/lookup.c | 11 ++++++-----
    fs/unionfs/union.h | 47 +++++++++++++++++++++++++++++++++++++++--------
    4 files changed, 60 insertions(+), 15 deletions(-)

    diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
    index c7bbeca..0be958f 100644
    --- a/fs/unionfs/dentry.c
    +++ b/fs/unionfs/dentry.c
    @@ -450,9 +450,11 @@ static void unionfs_d_release(struct dentry *dentry)
    bend = dbend(dentry);
    for (bindex = bstart; bindex <= bend; bindex++) {
    dput(unionfs_lower_dentry_idx(dentry, bindex));
    - unionfs_mntput(dentry, bindex);
    -
    unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
    + /* NULL lower mnt is ok if this is a negative dentry */
    + if (!dentry->d_inode && !unionfs_lower_mnt_idx(dentry,bindex))
    + continue;
    + unionfs_mntput(dentry, bindex);
    unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
    }
    /* free private data (unionfs_dentry_info) here */
    diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
    index a219a40..d6a79d5 100644
    --- a/fs/unionfs/inode.c
    +++ b/fs/unionfs/inode.c
    @@ -222,8 +222,11 @@ out:
    dput(wh_dentry);
    kfree(name);

    + if (!err)
    + unionfs_postcopyup_setmnt(dentry);
    unionfs_unlock_dentry(dentry);
    unionfs_read_unlock(dentry->d_sb);
    +
    return err;
    }

    @@ -563,8 +566,12 @@ out:
    d_drop(dentry);

    kfree(name);
    + if (!err)
    + unionfs_postcopyup_setmnt(dentry);
    unionfs_unlock_dentry(dentry);
    +
    unionfs_read_unlock(dentry->d_sb);
    +
    return err;
    }

    @@ -835,8 +842,12 @@ out:

    kfree(name);

    + if (!err)
    + unionfs_postcopyup_setmnt(dentry);
    unionfs_unlock_dentry(dentry);
    +
    unionfs_read_unlock(dentry->d_sb);
    +
    return err;
    }

    diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
    index 152d421..38ee21f 100644
    --- a/fs/unionfs/lookup.c
    +++ b/fs/unionfs/lookup.c
    @@ -314,24 +314,25 @@ out_negative:
    if (lookupmode == INTERPOSE_REVAL) {
    if (dentry->d_inode)
    UNIONFS_I(dentry->d_inode)->stale = 1;
    -
    goto out;
    }
    /* This should only happen if we found a whiteout. */
    if (first_dentry_offset == -1) {
    first_lower_dentry = lookup_one_len(name, lower_dir_dentry,
    - namelen);
    + namelen);
    first_dentry_offset = bindex;
    if (IS_ERR(first_lower_dentry)) {
    err = PTR_ERR(first_lower_dentry);
    goto out;
    }
    -
    - /* FIXME: the following line needs to be changed to allow
    +
    + /*
    + * FIXME: the following line needs to be changed to allow
    * mount-point crossing
    */
    first_dentry = dentry;
    - first_lower_mnt = unionfs_mntget(dentry, bindex);
    + first_lower_mnt = unionfs_mntget(dentry->d_sb->s_root,
    + bindex);
    }
    unionfs_set_lower_dentry_idx(dentry, first_dentry_offset,
    first_lower_dentry);
    diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
    index 9f3e68a..33c2137 100644
    --- a/fs/unionfs/union.h
    +++ b/fs/unionfs/union.h
    @@ -459,18 +459,49 @@ static inline void unlock_dir(struct dentry *dir)
    static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
    int bindex)
    {
    - BUG_ON(!dentry || bindex < 0);
    -
    - return mntget(unionfs_lower_mnt_idx(dentry, bindex));
    + struct vfsmount *mnt;
    +
    + if (!dentry) {
    + if (bindex < 0)
    + return NULL;
    + if (!dentry && bindex >= 0) {
    + return NULL;
    + }
    + }
    + mnt = unionfs_lower_mnt_idx(dentry, bindex);
    + if (!mnt) {
    + if (bindex < 0)
    + return NULL;
    + if (!mnt && bindex >= 0) {
    + return NULL;
    + }
    + }
    + mnt = mntget(mnt);
    + return mnt;
    }

    static inline void unionfs_mntput(struct dentry *dentry, int bindex)
    {
    - if (!dentry)
    - return;
    + struct vfsmount *mnt;
    +
    + if (!dentry) {
    + if (bindex < 0)
    + return;
    + if (!dentry && bindex >= 0) {
    + return;
    + }
    + }
    + mnt = unionfs_lower_mnt_idx(dentry, bindex);
    + if (!mnt) {
    + if (bindex < 0)
    + return;
    + if (!mnt && bindex >= 0) {
    + return;
    + }
    + }
    + mntput(mnt);
    +}
    +

    - BUG_ON(bindex < 0);

    - mntput(unionfs_lower_mnt_idx(dentry, bindex));
    -}
    #endif /* not _UNION_H_ */
    --
    1.5.2.2.238.g7cbf2f2
    -
    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/

    \
     
     \ /
      Last update: 2007-09-03 04:31    [W:4.169 / U:0.168 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site