diff options
| -rw-r--r-- | fs/fuse/dir.c | 12 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 2 |
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 | ||
| 1294 | found: | 1298 | found: |
| 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 { | |||
| 115 | enum { | 115 | enum { |
| 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 | }; |
