aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c31
-rw-r--r--fs/fuse/fuse_i.h9
-rw-r--r--fs/fuse/inode.c1
3 files changed, 38 insertions, 3 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index aa0b6ade0e68..dc5e64893375 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -14,6 +14,27 @@
14#include <linux/namei.h> 14#include <linux/namei.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16 16
17static bool fuse_use_readdirplus(struct inode *dir, struct file *filp)
18{
19 struct fuse_conn *fc = get_fuse_conn(dir);
20 struct fuse_inode *fi = get_fuse_inode(dir);
21
22 if (!fc->do_readdirplus)
23 return false;
24 if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
25 return true;
26 if (filp->f_pos == 0)
27 return true;
28 return false;
29}
30
31static void fuse_advise_use_readdirplus(struct inode *dir)
32{
33 struct fuse_inode *fi = get_fuse_inode(dir);
34
35 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
36}
37
17#if BITS_PER_LONG >= 64 38#if BITS_PER_LONG >= 64
18static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 39static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
19{ 40{
@@ -219,6 +240,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
219 attr_version); 240 attr_version);
220 fuse_change_entry_timeout(entry, &outarg); 241 fuse_change_entry_timeout(entry, &outarg);
221 } 242 }
243 fuse_advise_use_readdirplus(inode);
222 return 1; 244 return 1;
223} 245}
224 246
@@ -355,6 +377,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
355 else 377 else
356 fuse_invalidate_entry_cache(entry); 378 fuse_invalidate_entry_cache(entry);
357 379
380 fuse_advise_use_readdirplus(dir);
358 return newent; 381 return newent;
359 382
360 out_iput: 383 out_iput:
@@ -1290,7 +1313,7 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
1290 1313
1291static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) 1314static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1292{ 1315{
1293 int err; 1316 int plus, err;
1294 size_t nbytes; 1317 size_t nbytes;
1295 struct page *page; 1318 struct page *page;
1296 struct inode *inode = file->f_path.dentry->d_inode; 1319 struct inode *inode = file->f_path.dentry->d_inode;
@@ -1310,11 +1333,13 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1310 fuse_put_request(fc, req); 1333 fuse_put_request(fc, req);
1311 return -ENOMEM; 1334 return -ENOMEM;
1312 } 1335 }
1336
1337 plus = fuse_use_readdirplus(inode, file);
1313 req->out.argpages = 1; 1338 req->out.argpages = 1;
1314 req->num_pages = 1; 1339 req->num_pages = 1;
1315 req->pages[0] = page; 1340 req->pages[0] = page;
1316 req->page_descs[0].length = PAGE_SIZE; 1341 req->page_descs[0].length = PAGE_SIZE;
1317 if (fc->do_readdirplus) { 1342 if (plus) {
1318 attr_version = fuse_get_attr_version(fc); 1343 attr_version = fuse_get_attr_version(fc);
1319 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, 1344 fuse_read_fill(req, file, file->f_pos, PAGE_SIZE,
1320 FUSE_READDIRPLUS); 1345 FUSE_READDIRPLUS);
@@ -1327,7 +1352,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
1327 err = req->out.h.error; 1352 err = req->out.h.error;
1328 fuse_put_request(fc, req); 1353 fuse_put_request(fc, req);
1329 if (!err) { 1354 if (!err) {
1330 if (fc->do_readdirplus) { 1355 if (plus) {
1331 err = parse_dirplusfile(page_address(page), nbytes, 1356 err = parse_dirplusfile(page_address(page), nbytes,
1332 file, dstbuf, filldir, 1357 file, dstbuf, filldir,
1333 attr_version); 1358 attr_version);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index af51c146a9ae..fc55dd33c1e2 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -106,6 +106,15 @@ struct fuse_inode {
106 106
107 /** List of writepage requestst (pending or sent) */ 107 /** List of writepage requestst (pending or sent) */
108 struct list_head writepages; 108 struct list_head writepages;
109
110 /** Miscellaneous bits describing inode state */
111 unsigned long state;
112};
113
114/** FUSE inode state bits */
115enum {
116 /** Advise readdirplus */
117 FUSE_I_ADVISE_RDPLUS,
109}; 118};
110 119
111struct fuse_conn; 120struct fuse_conn;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 79b70deb7cd6..9876a87255fe 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -92,6 +92,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
92 fi->attr_version = 0; 92 fi->attr_version = 0;
93 fi->writectr = 0; 93 fi->writectr = 0;
94 fi->orig_ino = 0; 94 fi->orig_ino = 0;
95 fi->state = 0;
95 INIT_LIST_HEAD(&fi->write_files); 96 INIT_LIST_HEAD(&fi->write_files);
96 INIT_LIST_HEAD(&fi->queued_writes); 97 INIT_LIST_HEAD(&fi->queued_writes);
97 INIT_LIST_HEAD(&fi->writepages); 98 INIT_LIST_HEAD(&fi->writepages);