Unionfs: port to 3.13-rc1
authorErez Zadok <ezk@cs.sunysb.edu>
Thu, 28 Nov 2013 01:00:53 +0000 (20:00 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Sun, 27 Apr 2014 02:28:21 +0000 (22:28 -0400)
Use file_inode helper.

Add NULL extra arg to vfs_* methods and notify_change where it takes a
delegated inode.

Check DCACHE_OP_REVALIDATE flag in ->d_revalidate.

->setattr implemented, but not used yet.

Force our root dentry to be of type DIR.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
12 files changed:
fs/unionfs/commonfops.c
fs/unionfs/copyup.c
fs/unionfs/dentry.c
fs/unionfs/dirfops.c
fs/unionfs/file.c
fs/unionfs/inode.c
fs/unionfs/main.c
fs/unionfs/rdstate.c
fs/unionfs/rename.c
fs/unionfs/sioq.c
fs/unionfs/unlink.c
fs/unionfs/whiteout.c

index 9dc89e16c95660de3db992cf22d56eee7ef33a9b..5e7da8f8223748740cf99adeee9d8a832aa32304 100644 (file)
@@ -120,7 +120,7 @@ retry:
        dput(tmp_dentry);
 
        err = copyup_named_file(parent->d_inode, file, name, bstart, bindex,
-                               i_size_read(file->f_path.dentry->d_inode));
+                               i_size_read(file_inode(file)));
        if (err) {
                if (unlikely(err == -EEXIST))
                        goto retry;
@@ -135,7 +135,7 @@ retry:
                                            lower_dentry->d_inode);
        }
        lower_dir_dentry = lock_parent(lower_dentry);
-       err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
+       err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL);
        unlock_dir(lower_dir_dentry);
 
 out:
@@ -745,7 +745,7 @@ int unionfs_file_release(struct inode *inode, struct file *file)
        if (!err)
                unionfs_check_file(file);
        fileinfo = UNIONFS_F(file);
-       BUG_ON(file->f_path.dentry->d_inode != inode);
+       BUG_ON(file_inode(file) != inode);
        inodeinfo = UNIONFS_I(inode);
 
        /* fput all the lower files */
index 6b24957e8454b638fff0b447327ff3b12bacaf50..7ccecde938750a00e0f3bbcda8ff56de069cef91 100644 (file)
@@ -145,14 +145,14 @@ static int copyup_permissions(struct super_block *sb,
                ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
                ATTR_GID | ATTR_UID;
        mutex_lock(&new_lower_dentry->d_inode->i_mutex);
-       err = notify_change(new_lower_dentry, &newattrs);
+       err = notify_change(new_lower_dentry, &newattrs, NULL);
        if (err)
                goto out;
 
        /* now try to change the mode and ignore EOPNOTSUPP on symlinks */
        newattrs.ia_mode = i->i_mode;
        newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
-       err = notify_change(new_lower_dentry, &newattrs);
+       err = notify_change(new_lower_dentry, &newattrs, NULL);
        if (err == -EOPNOTSUPP &&
            S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
                printk(KERN_WARNING
@@ -498,7 +498,7 @@ out_unlink:
         * quota, or something else happened so let's unlink; we don't
         * really care about the return value of vfs_unlink
         */
-       vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
+       vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry, NULL);
 
        if (copyup_file) {
                /* need to close the file */
index 2183e5c3e7364017fde3bd6cac1da961065b0136..c7aeaebc73ae2586b152c90165ed993ad2cbe241 100644 (file)
@@ -302,6 +302,7 @@ static int unionfs_d_revalidate(struct dentry *dentry, unsigned int flags)
        bool valid = true;
        int err = 1;            /* 1 means valid for the VFS */
        struct dentry *parent;
+       struct dentry *lower_dentry;
 
        if (flags & LOOKUP_RCU)
                return -ECHILD;
@@ -310,6 +311,10 @@ static int unionfs_d_revalidate(struct dentry *dentry, unsigned int flags)
        parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
        unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
 
+       lower_dentry = unionfs_lower_dentry(dentry);
+       if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
+               goto out;
+
        valid = __unionfs_d_revalidate(dentry, parent, false, flags);
        if (valid) {
                unionfs_postcopyup_setmnt(dentry);
@@ -318,6 +323,8 @@ static int unionfs_d_revalidate(struct dentry *dentry, unsigned int flags)
                d_drop(dentry);
                err = valid;
        }
+
+out:
        unionfs_unlock_dentry(dentry);
        unionfs_unlock_parent(dentry, parent);
        unionfs_read_unlock(dentry->d_sb);
index 7b2f3cfd8aff2ad9bbbf92ef4869486fb96e8225..5797763ad4b56465d257fcf3ff6d4066a27e59c5 100644 (file)
@@ -169,8 +169,7 @@ static int unionfs_readdir(struct file *file, struct dir_context *ctx)
                uds->dirpos = offset;
 
                /* Copy the atime. */
-               fsstack_copy_attr_atime(inode,
-                                       lower_file->f_path.dentry->d_inode);
+               fsstack_copy_attr_atime(inode, file_inode(lower_file));
 
                if (err < 0)
                        goto out;
index f67db0ab6e669217785fda3ac02727d8f0c24248..f9cfc24bcd89dd07636ae08ed30a3998191f1785 100644 (file)
@@ -39,7 +39,7 @@ static ssize_t unionfs_read(struct file *file, char __user *buf,
        /* update our inode atime upon a successful lower read */
        if (err >= 0) {
                fsstack_copy_attr_atime(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                unionfs_check_file(file);
        }
 
@@ -71,9 +71,9 @@ static ssize_t unionfs_write(struct file *file, const char __user *buf,
        /* update our inode times+sizes upon a successful lower write */
        if (err >= 0) {
                fsstack_copy_inode_size(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                fsstack_copy_attr_times(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
                unionfs_check_file(file);
        }
@@ -320,7 +320,7 @@ static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos,
        /* update our inode atime upon a successful lower splice-read */
        if (err >= 0) {
                fsstack_copy_attr_atime(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                unionfs_check_file(file);
        }
 
@@ -353,9 +353,9 @@ static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe,
        /* update our inode times+sizes upon a successful lower write */
        if (err >= 0) {
                fsstack_copy_inode_size(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                fsstack_copy_attr_times(dentry->d_inode,
-                                       lower_file->f_path.dentry->d_inode);
+                                       file_inode(lower_file));
                unionfs_check_file(file);
        }
 
index 42a24fb88809ea8136db9847bac5c170e046a961..d22935ec3c9381f4111fe5310c145192c8fa6f07 100644 (file)
@@ -275,7 +275,7 @@ static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
                /* see Documentation/filesystems/unionfs/issues.txt */
                lockdep_off();
                err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
-                              lower_new_dentry);
+                              lower_new_dentry, NULL);
                lockdep_on();
        }
        unlock_dir(lower_dir_dentry);
@@ -304,7 +304,7 @@ docopyup:
                        /* do vfs_link */
                        err = vfs_link(lower_old_dentry,
                                       lower_dir_dentry->d_inode,
-                                      lower_new_dentry);
+                                      lower_new_dentry, NULL);
                        lockdep_on();
                        unlock_dir(lower_dir_dentry);
                        goto check_link;
@@ -999,7 +999,7 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
        }
 
        mutex_lock(&lower_dentry->d_inode->i_mutex);
-       err = notify_change(lower_dentry, &lower_ia);
+       err = notify_change(lower_dentry, &lower_ia, NULL);
        mutex_unlock(&lower_dentry->d_inode->i_mutex);
        if (err)
                goto out;
@@ -1031,6 +1031,45 @@ out_err:
        return err;
 }
 
+#if 0
+// XXX: may need this code in future
+static int unionfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                          struct kstat *stat)
+{
+       int err;
+       struct dentry *parent;
+       struct kstat lower_stat;
+       struct path lower_path;
+
+       unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
+       parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
+       unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
+
+       if (unlikely(!__unionfs_d_revalidate(dentry, parent, false, 0))) {
+               err = -ESTALE;
+               goto out;
+       }
+
+       lower_path.dentry = unionfs_lower_dentry(dentry);
+       lower_path.mnt = unionfs_lower_mnt(dentry);
+       err = vfs_getattr(&lower_path, &lower_stat);
+       if (err)
+               goto out;
+       fsstack_copy_attr_all(dentry->d_inode,
+                             lower_path.dentry->d_inode);
+       generic_fillattr(dentry->d_inode, stat);
+       stat->blocks = lower_stat.blocks;
+
+out:
+       unionfs_check_dentry(dentry);
+       unionfs_unlock_dentry(dentry);
+       unionfs_unlock_parent(dentry, parent);
+       unionfs_read_unlock(dentry->d_sb);
+
+       return err;
+}
+#endif
+
 struct inode_operations unionfs_symlink_iops = {
        .readlink       = unionfs_readlink,
        .permission     = unionfs_permission,
index 78f8c1a0917a46c5ba1e5c73c465eafe536dc486..270f55de17ee075bcd94d6b4632d4a18923bb90a 100644 (file)
@@ -599,7 +599,18 @@ static int unionfs_read_super(struct super_block *sb, void *raw_data,
                err = PTR_ERR(inode);
                goto out_dput;
        }
+       /*
+        * Have to set DIR mode temporarily on inode and dentry, before
+        * calling make_root, because make_root sets the
+        * DCACHE_DIRECTORY_TYPE dentry flag only if the inode is of type
+        * dir.  Now, later below, we'll be copying the lower inode
+        * attributes anyway, which'll set our inode's mode to type==DIR,
+        * but it's too late for the dentry to have the
+        * DCACHE_DIRECTORY_TYPE flag set.
+        */
+       inode->i_mode = S_IFDIR | 0755;
        sb->s_root = d_make_root(inode);
+       d_set_type(sb->s_root, DCACHE_DIRECTORY_TYPE);
        if (unlikely(!sb->s_root)) {
                err = -ENOMEM;
                goto out_iput;
index 59b7333b88a908388de5218c4fdbc1d2281294cb..fe0081c218427b9640f9bdf12c059fdf2544a741 100644 (file)
@@ -92,7 +92,7 @@ int init_rdstate(struct file *file)
               (sizeof(unsigned int) + sizeof(unsigned int)));
        BUG_ON(UNIONFS_F(file)->rdstate != NULL);
 
-       UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
+       UNIONFS_F(file)->rdstate = alloc_rdstate(file_inode(file),
                                                 fbstart(file));
 
        return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
index 912c1e9e33d974d9f33af7f3c69937f71daff63d..25377a33833a33bd7b1d178d820440c3eadf4a36 100644 (file)
@@ -120,7 +120,8 @@ static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                goto out_err_unlock;
        }
        err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-                        lower_new_dir_dentry->d_inode, lower_new_dentry);
+                        lower_new_dir_dentry->d_inode, lower_new_dentry,
+                        NULL);
 out_err_unlock:
        if (!err) {
                /* update parent dir times */
@@ -202,7 +203,7 @@ static int do_unionfs_rename(struct inode *old_dir,
                err = is_robranch_super(old_dir->i_sb, bindex);
                if (!err)
                        err = vfs_unlink(unlink_dir_dentry->d_inode,
-                                        unlink_dentry);
+                                        unlink_dentry, NULL);
 
                fsstack_copy_attr_times(new_parent->d_inode,
                                        unlink_dir_dentry->d_inode);
index 3c8eb77037924d46e2a72f8950c82cb8d13bdf75..bdb71f845a72ea2938e90cf0752ddd4188d5dc4f 100644 (file)
@@ -96,6 +96,6 @@ void __unionfs_unlink(struct work_struct *work)
        struct sioq_args *args = container_of(work, struct sioq_args, work);
        struct unlink_args *u = &args->unlink;
 
-       args->err = vfs_unlink(u->parent, u->dentry);
+       args->err = vfs_unlink(u->parent, u->dentry, NULL);
        complete(&args->comp);
 }
index 50cbd546a7a1421a8bf7038401d94a721d9df5a0..37508eb6cdcbbdef99b26a2a6b5547ef352ad2a1 100644 (file)
@@ -72,10 +72,10 @@ static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry,
                        lockdep_off();
                        if (!S_ISDIR(lower_dentry->d_inode->i_mode))
                                err = vfs_unlink(lower_dir_dentry->d_inode,
-                                                               lower_dentry);
+                                                lower_dentry, NULL);
                        else
                                err = vfs_rmdir(lower_dir_dentry->d_inode,
-                                                               lower_dentry);
+                                               lower_dentry);
                        lockdep_on();
                }
 
index 41c9b09f7df93eba108a9240416d3944fb4a9b00..94a9c24f5825d30599b64e5019b7aa0e15414564 100644 (file)
@@ -171,7 +171,7 @@ int unlink_whiteout(struct dentry *wh_dentry)
 
        /* see Documentation/filesystems/unionfs/issues.txt */
        lockdep_off();
-       err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
+       err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry, NULL);
        lockdep_on();
        unlock_dir(lower_dir_dentry);
 
@@ -397,7 +397,8 @@ static int do_delete_whiteouts(struct dentry *dentry, int bindex,
                                break;
                        }
                        if (lower_dentry->d_inode)
-                               err = vfs_unlink(lower_dir, lower_dentry);
+                               err = vfs_unlink(lower_dir, lower_dentry,
+                                                NULL);
                        dput(lower_dentry);
                        if (err)
                                break;