Wrapfs: use d_splice_alias
authorErez Zadok <ezk@cs.sunysb.edu>
Sun, 22 May 2016 05:27:13 +0000 (01:27 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Tue, 27 Dec 2016 03:11:41 +0000 (22:11 -0500)
Refactor interpose code to allow lookup to use d_splice_alias.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/wrapfs/lookup.c

index ef47e71489b1dc406d1c87dcb455ee32327f769a..2edbeb59ffb9da109be1d46ff80bec8cf4084429 100644 (file)
@@ -144,27 +144,24 @@ struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode)
 }
 
 /*
- * Connect a wrapfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: wrapfs's dentry which interposes on lower one
- * @sb: wrapfs's super_block
- * @lower_path: the lower path (caller does path_get/put)
+ * Helper interpose routine, called directly by ->lookup to handle
+ * spliced dentries.
  */
-int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
-                    struct path *lower_path)
+static struct dentry *__wrapfs_interpose(struct dentry *dentry,
+                                        struct super_block *sb,
+                                        struct path *lower_path)
 {
-       int err = 0;
        struct inode *inode;
        struct inode *lower_inode;
        struct super_block *lower_sb;
+       struct dentry *ret_dentry;
 
        lower_inode = lower_path->dentry->d_inode;
        lower_sb = wrapfs_lower_super(sb);
 
        /* check that the lower file system didn't cross a mount point */
        if (lower_inode->i_sb != lower_sb) {
-               err = -EXDEV;
+               ret_dentry = ERR_PTR(-EXDEV);
                goto out;
        }
 
@@ -176,14 +173,31 @@ int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
        /* inherit lower inode number for wrapfs's inode */
        inode = wrapfs_iget(sb, lower_inode);
        if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
+               ret_dentry = ERR_PTR(PTR_ERR(inode));
                goto out;
        }
 
-       d_add(dentry, inode);
+       ret_dentry = d_splice_alias(inode, dentry);
 
 out:
-       return err;
+       return ret_dentry;
+}
+
+/*
+ * Connect a wrapfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: wrapfs's dentry which interposes on lower one
+ * @sb: wrapfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
+                    struct path *lower_path)
+{
+       struct dentry *ret_dentry;
+
+       ret_dentry = __wrapfs_interpose(dentry, sb, lower_path);
+       return PTR_ERR(ret_dentry);
 }
 
 /*
@@ -202,6 +216,7 @@ static struct dentry *__wrapfs_lookup(struct dentry *dentry, int flags,
        const char *name;
        struct path lower_path;
        struct qstr this;
+       struct dentry *ret_dentry = NULL;
 
        /* must initialize dentry operations */
        d_set_d_op(dentry, &wrapfs_dops);
@@ -222,9 +237,13 @@ static struct dentry *__wrapfs_lookup(struct dentry *dentry, int flags,
        /* no error: handle positive dentries */
        if (!err) {
                wrapfs_set_lower_path(dentry, &lower_path);
-               err = wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
-               if (err) /* path_put underlying path on error */
+               ret_dentry =
+                       __wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
+               if (IS_ERR(ret_dentry)) {
+                       err = PTR_ERR(ret_dentry);
+                        /* path_put underlying path on error */
                        wrapfs_put_reset_lower_path(dentry);
+               }
                goto out;
        }
 
@@ -264,7 +283,9 @@ setup_lower:
                err = 0;
 
 out:
-       return ERR_PTR(err);
+       if (err)
+               return ERR_PTR(err);
+       return ret_dentry;
 }
 
 struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,