|
@@ -182,6 +182,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
|
|
|
struct inode *inode;
|
|
|
struct dentry *parent;
|
|
|
struct fuse_conn *fc;
|
|
|
+ struct fuse_inode *fi;
|
|
|
int ret;
|
|
|
|
|
|
inode = ACCESS_ONCE(entry->d_inode);
|
|
@@ -228,7 +229,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
|
|
|
if (!err && !outarg.nodeid)
|
|
|
err = -ENOENT;
|
|
|
if (!err) {
|
|
|
- struct fuse_inode *fi = get_fuse_inode(inode);
|
|
|
+ fi = get_fuse_inode(inode);
|
|
|
if (outarg.nodeid != get_node_id(inode)) {
|
|
|
fuse_queue_forget(fc, forget, outarg.nodeid, 1);
|
|
|
goto invalid;
|
|
@@ -246,8 +247,11 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
|
|
|
attr_version);
|
|
|
fuse_change_entry_timeout(entry, &outarg);
|
|
|
} else if (inode) {
|
|
|
- fc = get_fuse_conn(inode);
|
|
|
- if (fc->readdirplus_auto) {
|
|
|
+ fi = get_fuse_inode(inode);
|
|
|
+ if (flags & LOOKUP_RCU) {
|
|
|
+ if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
|
|
|
+ return -ECHILD;
|
|
|
+ } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
|
|
|
parent = dget_parent(entry);
|
|
|
fuse_advise_use_readdirplus(parent->d_inode);
|
|
|
dput(parent);
|
|
@@ -1292,6 +1296,8 @@ static int fuse_direntplus_link(struct file *file,
|
|
|
}
|
|
|
|
|
|
found:
|
|
|
+ if (fc->readdirplus_auto)
|
|
|
+ set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
|
|
|
fuse_change_entry_timeout(dentry, o);
|
|
|
|
|
|
err = 0;
|