Skip to content

Commit

Permalink
fuse: fix readdirplus Oops in fuse_dentry_revalidate
Browse files Browse the repository at this point in the history
Fix bug introduced by commit 4582a4a "FUSE: Adapt readdirplus to application
usage patterns".

We need to check for a positive dentry; negative dentries are not added by
readdirplus.  Secondly we need to advise the use of readdirplus on the *parent*,
otherwise the whole thing is useless.  Thirdly all this is only relevant if
"readdirplus_auto" mode is selected by the filesystem.

We advise the use of readdirplus only if the dentry was still valid.  If we had
to redo the lookup then there was no use in doing the -plus version.

Reported-by: Bernd Schubert <bernd.schubert@itwm.fraunhofer.de>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Feng Shuo <steve.shuo.feng@gmail.com>
CC: stable@vger.kernel.org
  • Loading branch information
Miklos Szeredi committed Jun 3, 2013
1 parent bee6c30 commit 28420da
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
12 changes: 9 additions & 3 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,17 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
{
struct inode *inode;
struct dentry *parent;
struct fuse_conn *fc;

inode = ACCESS_ONCE(entry->d_inode);
if (inode && is_bad_inode(inode))
return 0;
else if (fuse_dentry_time(entry) < get_jiffies_64()) {
int err;
struct fuse_entry_out outarg;
struct fuse_conn *fc;
struct fuse_req *req;
struct fuse_forget_link *forget;
struct dentry *parent;
u64 attr_version;

/* For negative dentries, always do a fresh lookup */
Expand Down Expand Up @@ -241,8 +241,14 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
entry_attr_timeout(&outarg),
attr_version);
fuse_change_entry_timeout(entry, &outarg);
} else if (inode) {
fc = get_fuse_conn(inode);
if (fc->readdirplus_auto) {
parent = dget_parent(entry);
fuse_advise_use_readdirplus(parent->d_inode);
dput(parent);
}
}
fuse_advise_use_readdirplus(inode);
return 1;
}

Expand Down
7 changes: 4 additions & 3 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,10 +867,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->dont_mask = 1;
if (arg->flags & FUSE_AUTO_INVAL_DATA)
fc->auto_inval_data = 1;
if (arg->flags & FUSE_DO_READDIRPLUS)
if (arg->flags & FUSE_DO_READDIRPLUS) {
fc->do_readdirplus = 1;
if (arg->flags & FUSE_READDIRPLUS_AUTO)
fc->readdirplus_auto = 1;
if (arg->flags & FUSE_READDIRPLUS_AUTO)
fc->readdirplus_auto = 1;
}
if (arg->flags & FUSE_ASYNC_DIO)
fc->async_dio = 1;
} else {
Expand Down

0 comments on commit 28420da

Please sign in to comment.