From: Feng S. <ste...@gm...> - 2013-01-31 15:17:15
|
Miklos, Are you using the "for-next" branch of the following tree? http://git.kernel.org/?p=linux/kernel/git/mszeredi/fuse.git;a=summary I didn't see the first part applied. If not, I could rebase to that branch and send a patch set with the second part split out as a separated patch. On Fri, Jan 25, 2013 at 10:16 PM, Miklos Szeredi <mi...@sz...> wrote: > On Tue, Jan 15, 2013 at 4:23 AM, Feng Shuo <ste...@gm...> wrote: >> Use the same adaptive readdirplus mechanism as NFS: >> >> http://permalink.gmane.org/gmane.linux.nfs/49299 > > OK, applied with minor updates. > >> If the user space implementation wants to disable readdirplus >> temporarily, it could just return ENOTSUPP. Then kernel will >> recall it with readdir. > > I removed this part. It may make sense, but it's not part of the > adaptive readdirplus algorithm, so I'd like to see this as a separate > patch. > > Thanks, > Miklos > > > >> Signed-off-by: Feng Shuo <ste...@gm...> >> --- >> fs/fuse/dir.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- >> fs/fuse/fuse_i.h | 10 ++++++++++ >> fs/fuse/inode.c | 3 +++ >> 3 files changed, 59 insertions(+), 4 deletions(-) >> >> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c >> index dcc1e52..b9975df 100644 >> --- a/fs/fuse/dir.c >> +++ b/fs/fuse/dir.c >> @@ -14,6 +14,34 @@ >> #include <linux/namei.h> >> #include <linux/slab.h> >> >> +static bool fuse_use_readdirplus(struct inode *dir, struct file *filp) >> +{ >> + struct fuse_conn *fc = get_fuse_conn(dir); >> + struct fuse_inode *fi = get_fuse_inode(dir); >> + >> + if (!fc->do_readdirplus) >> + return false; >> + if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) >> + return true; >> + if (filp->f_pos == 0) >> + return true; >> + return false; >> +} >> + >> +static void fuse_advise_use_readdirplus(struct inode *dir) >> +{ >> + struct fuse_inode *fi = get_fuse_inode(dir); >> + >> + set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); >> +} >> + >> +static void fuse_stop_use_readdirplus(struct inode *dir) >> +{ >> + struct fuse_inode *fi = get_fuse_inode(dir); >> + >> + clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); >> +} >> + >> #if BITS_PER_LONG >= 64 >> static inline void fuse_dentry_settime(struct dentry *entry, u64 time) >> { >> @@ -219,6 +247,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) >> attr_version); >> fuse_change_entry_timeout(entry, &outarg); >> } >> + fuse_advise_use_readdirplus(inode); >> return 1; >> } >> >> @@ -355,6 +384,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, >> else >> fuse_invalidate_entry_cache(entry); >> >> + fuse_advise_use_readdirplus(dir); >> return newent; >> >> out_iput: >> @@ -1294,7 +1324,7 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, >> >> static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) >> { >> - int err; >> + int plus, err; >> size_t nbytes; >> struct page *page; >> struct inode *inode = file->f_path.dentry->d_inode; >> @@ -1314,10 +1344,13 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) >> fuse_put_request(fc, req); >> return -ENOMEM; >> } >> + >> + plus = fuse_use_readdirplus(inode, file); >> +read_again: >> req->out.argpages = 1; >> req->num_pages = 1; >> req->pages[0] = page; >> - if (fc->do_readdirplus) { >> + if (plus) { >> attr_version = fuse_get_attr_version(fc); >> fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, >> FUSE_READDIRPLUS); >> @@ -1329,8 +1362,17 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) >> nbytes = req->out.args[0].size; >> err = req->out.h.error; >> fuse_put_request(fc, req); >> + if ((err == -ENOTSUPP) && plus) { >> + fuse_stop_use_readdirplus(inode); >> + plus = 0; >> + req = fuse_get_req(fc); >> + if (!IS_ERR(req)) >> + goto read_again; >> + err = PTR_ERR(req); >> + goto out; >> + } >> if (!err) { >> - if (fc->do_readdirplus) { >> + if (plus) { >> err = parse_dirplusfile(page_address(page), nbytes, >> file, dstbuf, filldir, >> attr_version); >> @@ -1339,7 +1381,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) >> dstbuf, filldir); >> } >> } >> - >> +out: >> __free_page(page); >> fuse_invalidate_attr(inode); /* atime changed */ >> return err; >> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h >> index 5c50553..e582603 100644 >> --- a/fs/fuse/fuse_i.h >> +++ b/fs/fuse/fuse_i.h >> @@ -103,6 +103,16 @@ struct fuse_inode { >> >> /** List of writepage requestst (pending or sent) */ >> struct list_head writepages; >> + >> + /** Miscellaneous bits describing inode state */ >> + unsigned long state; >> +}; >> + >> +/** FUSE inode state bits */ >> +enum { >> + /** Advise readdirplus */ >> + FUSE_I_ADVISE_RDPLUS, >> + /* FUSE_I_MTIME_UPDATED, */ >> }; >> >> struct fuse_conn; >> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c >> index 6f7d574..4ba1cf5 100644 >> --- a/fs/fuse/inode.c >> +++ b/fs/fuse/inode.c >> @@ -255,6 +255,9 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) >> new_decode_dev(attr->rdev)); >> } else >> BUG(); >> + >> + /* The readdir_plus is disabled initially. */ >> + get_fuse_inode(inode)->state = 0; >> } >> >> int fuse_inode_eq(struct inode *inode, void *_nodeidp) >> -- >> 1.7.12.4 >> >> >> ------------------------------------------------------------------------------ >> Master SQL Server Development, Administration, T-SQL, SSAS, SSIS, SSRS >> and more. Get SQL Server skills now (including 2012) with LearnDevNow - >> 200+ hours of step-by-step video tutorials by Microsoft MVPs and experts. >> SALE $99.99 this month only - learn more at: >> http://p.sf.net/sfu/learnmore_122512 >> _______________________________________________ >> fuse-devel mailing list >> fus...@li... >> https://lists.sourceforge.net/lists/listinfo/fuse-devel -- Feng Shuo Tel: (86)10-59851155-2116 Fax: (86)10-59851155-2008 Tianjin Zhongke Blue Whale Information Technologies Co., Ltd 10th Floor, Tower A, The GATE building, No. 19 Zhong-guan-cun Avenue Haidian District, Beijing, China Postcode 100080 |