aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c12
-rw-r--r--fs/fuse/fuse_i.h2
2 files changed, 11 insertions, 3 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 9b16806f11da..a75159846a75 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -182,6 +182,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
182 struct inode *inode; 182 struct inode *inode;
183 struct dentry *parent; 183 struct dentry *parent;
184 struct fuse_conn *fc; 184 struct fuse_conn *fc;
185 struct fuse_inode *fi;
185 int ret; 186 int ret;
186 187
187 inode = ACCESS_ONCE(entry->d_inode); 188 inode = ACCESS_ONCE(entry->d_inode);
@@ -228,7 +229,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
228 if (!err && !outarg.nodeid) 229 if (!err && !outarg.nodeid)
229 err = -ENOENT; 230 err = -ENOENT;
230 if (!err) { 231 if (!err) {
231 struct fuse_inode *fi = get_fuse_inode(inode); 232 fi = get_fuse_inode(inode);
232 if (outarg.nodeid != get_node_id(inode)) { 233 if (outarg.nodeid != get_node_id(inode)) {
233 fuse_queue_forget(fc, forget, outarg.nodeid, 1); 234 fuse_queue_forget(fc, forget, outarg.nodeid, 1);
234 goto invalid; 235 goto invalid;
@@ -246,8 +247,11 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
246 attr_version); 247 attr_version);
247 fuse_change_entry_timeout(entry, &outarg); 248 fuse_change_entry_timeout(entry, &outarg);
248 } else if (inode) { 249 } else if (inode) {
249 fc = get_fuse_conn(inode); 250 fi = get_fuse_inode(inode);
250 if (fc->readdirplus_auto) { 251 if (flags & LOOKUP_RCU) {
252 if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
253 return -ECHILD;
254 } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
251 parent = dget_parent(entry); 255 parent = dget_parent(entry);
252 fuse_advise_use_readdirplus(parent->d_inode); 256 fuse_advise_use_readdirplus(parent->d_inode);
253 dput(parent); 257 dput(parent);
@@ -1292,6 +1296,8 @@ static int fuse_direntplus_link(struct file *file,
1292 } 1296 }
1293 1297
1294found: 1298found:
1299 if (fc->readdirplus_auto)
1300 set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
1295 fuse_change_entry_timeout(dentry, o); 1301 fuse_change_entry_timeout(dentry, o);
1296 1302
1297 err = 0; 1303 err = 0;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5ced199b50bb..5b9e6f3b6aef 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -115,6 +115,8 @@ struct fuse_inode {
115enum { 115enum {
116 /** Advise readdirplus */ 116 /** Advise readdirplus */
117 FUSE_I_ADVISE_RDPLUS, 117 FUSE_I_ADVISE_RDPLUS,
118 /** Initialized with readdirplus */
119 FUSE_I_INIT_RDPLUS,
118 /** An operation changing file size is in progress */ 120 /** An operation changing file size is in progress */
119 FUSE_I_SIZE_UNSTABLE, 121 FUSE_I_SIZE_UNSTABLE,
120}; 122};