aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2017-03-09 22:11:08 -0800
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:35:25 +0200
commitbf110c341f6b4d09b882e5c302a343f323ae3aa9 (patch)
tree78ce4cd849312c5605b6b9b4070d6dcd9e47e2d2 /fs
parent3f0fdccbb6bfc06fc61933828bb8cdac8d1c9a5a (diff)
ANDROID: sdcardfs: use d_splice_alias
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
Diffstat (limited to 'fs')
-rwxr-xr-xfs/sdcardfs/lookup.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index b47ef16b5..6e1a17505 100755
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -169,27 +169,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;
}
@@ -201,14 +199,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 {
@@ -249,6 +265,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);
@@ -335,9 +352,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;
}
@@ -377,7 +398,9 @@ setup_lower:
err = 0;
out:
- return ERR_PTR(err);
+ if (err)
+ return ERR_PTR(err);
+ return ret_dentry;
}
/*