|
@@ -267,26 +267,6 @@ int fuse_valid_type(int m)
|
|
|
S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Add a directory inode to a dentry, ensuring that no other dentry
|
|
|
- * refers to this inode. Called with fc->inst_mutex.
|
|
|
- */
|
|
|
-static struct dentry *fuse_d_add_directory(struct dentry *entry,
|
|
|
- struct inode *inode)
|
|
|
-{
|
|
|
- struct dentry *alias = d_find_alias(inode);
|
|
|
- if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
|
|
|
- /* This tries to shrink the subtree below alias */
|
|
|
- fuse_invalidate_entry(alias);
|
|
|
- dput(alias);
|
|
|
- if (!hlist_empty(&inode->i_dentry))
|
|
|
- return ERR_PTR(-EBUSY);
|
|
|
- } else {
|
|
|
- dput(alias);
|
|
|
- }
|
|
|
- return d_splice_alias(inode, entry);
|
|
|
-}
|
|
|
-
|
|
|
int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
|
|
|
struct fuse_entry_out *outarg, struct inode **inode)
|
|
|
{
|
|
@@ -345,6 +325,24 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
|
|
|
+ struct inode *inode)
|
|
|
+{
|
|
|
+ struct dentry *newent;
|
|
|
+
|
|
|
+ if (inode && S_ISDIR(inode->i_mode)) {
|
|
|
+ struct fuse_conn *fc = get_fuse_conn(inode);
|
|
|
+
|
|
|
+ mutex_lock(&fc->inst_mutex);
|
|
|
+ newent = d_materialise_unique(dentry, inode);
|
|
|
+ mutex_unlock(&fc->inst_mutex);
|
|
|
+ } else {
|
|
|
+ newent = d_materialise_unique(dentry, inode);
|
|
|
+ }
|
|
|
+
|
|
|
+ return newent;
|
|
|
+}
|
|
|
+
|
|
|
static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
|
|
|
unsigned int flags)
|
|
|
{
|
|
@@ -352,7 +350,6 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
|
|
|
struct fuse_entry_out outarg;
|
|
|
struct inode *inode;
|
|
|
struct dentry *newent;
|
|
|
- struct fuse_conn *fc = get_fuse_conn(dir);
|
|
|
bool outarg_valid = true;
|
|
|
|
|
|
err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
|
|
@@ -368,16 +365,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
|
|
|
if (inode && get_node_id(inode) == FUSE_ROOT_ID)
|
|
|
goto out_iput;
|
|
|
|
|
|
- if (inode && S_ISDIR(inode->i_mode)) {
|
|
|
- mutex_lock(&fc->inst_mutex);
|
|
|
- newent = fuse_d_add_directory(entry, inode);
|
|
|
- mutex_unlock(&fc->inst_mutex);
|
|
|
- err = PTR_ERR(newent);
|
|
|
- if (IS_ERR(newent))
|
|
|
- goto out_iput;
|
|
|
- } else {
|
|
|
- newent = d_splice_alias(inode, entry);
|
|
|
- }
|
|
|
+ newent = fuse_materialise_dentry(entry, inode);
|
|
|
+ err = PTR_ERR(newent);
|
|
|
+ if (IS_ERR(newent))
|
|
|
+ goto out_err;
|
|
|
|
|
|
entry = newent ? newent : entry;
|
|
|
if (outarg_valid)
|
|
@@ -1275,18 +1266,10 @@ static int fuse_direntplus_link(struct file *file,
|
|
|
if (!inode)
|
|
|
goto out;
|
|
|
|
|
|
- if (S_ISDIR(inode->i_mode)) {
|
|
|
- mutex_lock(&fc->inst_mutex);
|
|
|
- alias = fuse_d_add_directory(dentry, inode);
|
|
|
- mutex_unlock(&fc->inst_mutex);
|
|
|
- err = PTR_ERR(alias);
|
|
|
- if (IS_ERR(alias)) {
|
|
|
- iput(inode);
|
|
|
- goto out;
|
|
|
- }
|
|
|
- } else {
|
|
|
- alias = d_splice_alias(inode, dentry);
|
|
|
- }
|
|
|
+ alias = fuse_materialise_dentry(dentry, inode);
|
|
|
+ err = PTR_ERR(alias);
|
|
|
+ if (IS_ERR(alias))
|
|
|
+ goto out;
|
|
|
|
|
|
if (alias) {
|
|
|
dput(dentry);
|