From: Erez Zadok Date: Sat, 30 Apr 2011 05:34:00 +0000 (-0400) Subject: Unionfs: pass nameidata when lower file system is NFS X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=5abb82a8013af84a2ca9c5a733ac82b941ff3e5a;p=unionfs-2.6.39.y.git Unionfs: pass nameidata when lower file system is NFS Use new lookup_one_len_nd() and pass nameidata, now required by NFS3, else you get an oops. Signed-off-by: Erez Zadok --- diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c index a0c3bbaf7c7..ccc02f49ed0 100644 --- a/fs/unionfs/dentry.c +++ b/fs/unionfs/dentry.c @@ -192,6 +192,9 @@ validate_lowers: bend = dbend(dentry); BUG_ON(bstart == -1); for (bindex = bstart; bindex <= bend; bindex++) { + int err; + struct nameidata lower_nd; + lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); if (!lower_dentry || !lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) @@ -204,8 +207,14 @@ validate_lowers: * invariants). We will open lower files as and when needed * later on. */ - if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL)) + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); + if (unlikely(err < 0)) { + valid = false; + break; + } + if (!lower_dentry->d_op->d_revalidate(lower_dentry, &lower_nd)) valid = false; + release_lower_nd(&lower_nd, err); } if (!dentry->d_inode || diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c index 936700e7358..c088fdb1a3d 100644 --- a/fs/unionfs/rename.c +++ b/fs/unionfs/rename.c @@ -28,6 +28,7 @@ static int unionfs_refresh_lower_dentry(struct dentry *dentry, struct dentry *lower_dentry; struct dentry *lower_parent; int err = 0; + struct nameidata lower_nd; verify_locked(dentry); @@ -35,8 +36,12 @@ static int unionfs_refresh_lower_dentry(struct dentry *dentry, BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode)); - lower_dentry = lookup_one_len(dentry->d_name.name, lower_parent, - dentry->d_name.len); + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); + if (unlikely(err < 0)) + goto out; + lower_dentry = lookup_one_len_nd(dentry->d_name.name, lower_parent, + dentry->d_name.len, &lower_nd); + release_lower_nd(&lower_nd, err); if (IS_ERR(lower_dentry)) { err = PTR_ERR(lower_dentry); goto out; diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h index b634babaa83..5b49fef0425 100644 --- a/fs/unionfs/union.h +++ b/fs/unionfs/union.h @@ -566,9 +566,19 @@ static inline struct dentry *lookup_lck_len(const char *name, struct dentry *base, int len) { struct dentry *d; + struct nameidata lower_nd; + int err; + + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); + if (unlikely(err < 0)) { + d = ERR_PTR(err); + goto out; + } mutex_lock(&base->d_inode->i_mutex); - d = lookup_one_len(name, base, len); + d = lookup_one_len_nd(name, base, len, &lower_nd); + release_lower_nd(&lower_nd, err); mutex_unlock(&base->d_inode->i_mutex); +out: return d; } diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c index 9abe5667f17..c823c1d77e3 100644 --- a/fs/unionfs/whiteout.c +++ b/fs/unionfs/whiteout.c @@ -481,6 +481,7 @@ int is_opaque_dir(struct dentry *dentry, int bindex) struct dentry *wh_lower_dentry; struct inode *lower_inode; struct sioq_args args; + struct nameidata lower_nd; lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); lower_inode = lower_dentry->d_inode; @@ -490,9 +491,16 @@ int is_opaque_dir(struct dentry *dentry, int bindex) mutex_lock(&lower_inode->i_mutex); if (!inode_permission(lower_inode, MAY_EXEC)) { + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); + if (unlikely(err < 0)) { + mutex_unlock(&lower_inode->i_mutex); + goto out; + } wh_lower_dentry = - lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry, - sizeof(UNIONFS_DIR_OPAQUE) - 1); + lookup_one_len_nd(UNIONFS_DIR_OPAQUE, lower_dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1, + &lower_nd); + release_lower_nd(&lower_nd, err); } else { args.is_opaque.dentry = lower_dentry; run_sioq(__is_opaque_dir, &args); @@ -517,9 +525,17 @@ out: void __is_opaque_dir(struct work_struct *work) { struct sioq_args *args = container_of(work, struct sioq_args, work); + struct nameidata lower_nd; + int err; - args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry, - sizeof(UNIONFS_DIR_OPAQUE) - 1); + err = init_lower_nd(&lower_nd, LOOKUP_OPEN); + if (unlikely(err < 0)) + return; + args->ret = lookup_one_len_nd(UNIONFS_DIR_OPAQUE, + args->is_opaque.dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1, + &lower_nd); + release_lower_nd(&lower_nd, err); complete(&args->comp); } @@ -555,8 +571,12 @@ int make_dir_opaque(struct dentry *dentry, int bindex) !S_ISDIR(lower_dir->i_mode)); mutex_lock(&lower_dir->i_mutex); - diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry, - sizeof(UNIONFS_DIR_OPAQUE) - 1); + err = init_lower_nd(&nd, LOOKUP_OPEN); + if (unlikely(err < 0)) + goto out; + diropq = lookup_one_len_nd(UNIONFS_DIR_OPAQUE, lower_dentry, + sizeof(UNIONFS_DIR_OPAQUE) - 1, &nd); + release_lower_nd(&nd, err); if (IS_ERR(diropq)) { err = PTR_ERR(diropq); goto out;