Unionfs: pass nameidata when lower file system is NFS
authorErez Zadok <ezk@cs.sunysb.edu>
Sat, 30 Apr 2011 05:34:00 +0000 (01:34 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Sat, 30 Apr 2011 05:34:00 +0000 (01:34 -0400)
Use new lookup_one_len_nd() and pass nameidata, now required by NFS3, else
you get an oops.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/dentry.c
fs/unionfs/rename.c
fs/unionfs/union.h
fs/unionfs/whiteout.c

index a0c3bbaf7c7853c6ac2ebbac376d9d4fc857364f..ccc02f49ed08046926ec57a31f5c117957fe7886 100644 (file)
@@ -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 ||
index 936700e735827904e88d15d637ccf59663de4cd8..c088fdb1a3d9fe1394cc2ea3b979b06cc51dbf7c 100644 (file)
@@ -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;
index b634babaa836a343d39251db33b3fedd22e6b030..5b49fef042522a71944afc103b7a98bb26edb695 100644 (file)
@@ -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;
 }
 
index 9abe5667f1747e913c0383e6fcb5f24e965a9792..c823c1d77e34ec209d1ab71b37fb71655d7570a9 100644 (file)
@@ -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;