ANDROID: sdcardfs: use d_splice_alias
authorDaniel Rosenberg <drosen@google.com>
Fri, 10 Mar 2017 06:11:08 +0000 (22:11 -0800)
committerStricted <info@stricted.net>
Thu, 11 Oct 2018 16:03:36 +0000 (18:03 +0200)
adapted from wrapfs
commit 9671770ff8b9 ("Wrapfs: use d_splice_alias")

Refactor interpose code to allow lookup to use d_splice_alias.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Bug: 35766959
Change-Id: Icf51db8658202c48456724275b03dc77f73f585b

fs/sdcardfs/lookup.c

index c2f29d95f06f3dc0bb16d96b18e6ff4133d9a326..dcf54a3e644c344313821e0796570e080a471151 100644 (file)
@@ -164,27 +164,25 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, u
 }
 
 /*
- * Connect a sdcardfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: sdcardfs's dentry which interposes on lower one
- * @sb: sdcardfs'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 sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
-                    struct path *lower_path, userid_t id)
+static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
+                                        struct super_block *sb,
+                                        struct path *lower_path,
+                                        userid_t id)
 {
-       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 = sdcardfs_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;
        }
 
@@ -196,14 +194,32 @@ int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
        /* inherit lower inode number for sdcardfs's inode */
        inode = sdcardfs_iget(sb, lower_inode, id);
        if (IS_ERR(inode)) {
-               err = PTR_ERR(inode);
+               ret_dentry = ERR_CAST(inode);
                goto out;
        }
 
-       d_add(dentry, inode);
+       ret_dentry = d_splice_alias(inode, dentry);
+       dentry = ret_dentry ?: dentry;
        update_derived_permission_lock(dentry);
 out:
-       return err;
+       return ret_dentry;
+}
+
+/*
+ * Connect an sdcardfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: sdcardfs's dentry which interposes on lower one
+ * @sb: sdcardfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
+                    struct path *lower_path, userid_t id)
+{
+       struct dentry *ret_dentry;
+
+       ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
+       return PTR_ERR(ret_dentry);
 }
 
 struct sdcardfs_name_data {
@@ -244,6 +260,7 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
        const struct qstr *name;
        struct path lower_path;
        struct qstr dname;
+       struct dentry *ret_dentry = NULL;
        struct sdcardfs_sb_info *sbi;
 
        sbi = SDCARDFS_SB(dentry->d_sb);
@@ -330,9 +347,13 @@ put_name:
                }
 
                sdcardfs_set_lower_path(dentry, &lower_path);
-               err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
-               if (err) /* path_put underlying path on error */
+               ret_dentry =
+                       __sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
+               if (IS_ERR(ret_dentry)) {
+                       err = PTR_ERR(ret_dentry);
+                        /* path_put underlying path on error */
                        sdcardfs_put_reset_lower_path(dentry);
+               }
                goto out;
        }
 
@@ -372,7 +393,9 @@ setup_lower:
                err = 0;
 
 out:
-       return ERR_PTR(err);
+       if (err)
+               return ERR_PTR(err);
+       return ret_dentry;
 }
 
 /*