diff options
author | Anand V. Avati <avati@redhat.com> | 2012-08-19 08:53:23 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-24 10:21:25 -0500 |
commit | 0b05b18381eea98c9c9ada95629bf659a88c9374 (patch) | |
tree | a6389eaffda03a2e28cb05be242e03ef839fcb91 /fs/fuse/dev.c | |
parent | ff7532ca2c631e7e96dcd305a967b610259dc0ea (diff) |
fuse: implement NFS-like readdirplus support
This patch implements readdirplus support in FUSE, similar to NFS.
The payload returned in the readdirplus call contains
'fuse_entry_out' structure thereby providing all the necessary inputs
for 'faking' a lookup() operation on the spot.
If the dentry and inode already existed (for e.g. in a re-run of ls -l)
then just the inode attributes timeout and dentry timeout are refreshed.
With a simple client->network->server implementation of a FUSE based
filesystem, the following performance observations were made:
Test: Performing a filesystem crawl over 20,000 files with
sh# time ls -lR /mnt
Without readdirplus:
Run 1: 18.1s
Run 2: 16.0s
Run 3: 16.2s
With readdirplus:
Run 1: 4.1s
Run 2: 3.8s
Run 3: 3.8s
The performance improvement is significant as it avoided 20,000 upcalls
calls (lookup). Cache consistency is no worse than what already is.
Signed-off-by: Anand V. Avati <avati@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index e83351aa5bad..05c3eec298f2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -491,6 +491,25 @@ void fuse_request_send_background_locked(struct fuse_conn *fc, | |||
491 | fuse_request_send_nowait_locked(fc, req); | 491 | fuse_request_send_nowait_locked(fc, req); |
492 | } | 492 | } |
493 | 493 | ||
494 | void fuse_force_forget(struct file *file, u64 nodeid) | ||
495 | { | ||
496 | struct inode *inode = file->f_path.dentry->d_inode; | ||
497 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
498 | struct fuse_req *req; | ||
499 | struct fuse_forget_in inarg; | ||
500 | |||
501 | memset(&inarg, 0, sizeof(inarg)); | ||
502 | inarg.nlookup = 1; | ||
503 | req = fuse_get_req_nofail(fc, file); | ||
504 | req->in.h.opcode = FUSE_FORGET; | ||
505 | req->in.h.nodeid = nodeid; | ||
506 | req->in.numargs = 1; | ||
507 | req->in.args[0].size = sizeof(inarg); | ||
508 | req->in.args[0].value = &inarg; | ||
509 | req->isreply = 0; | ||
510 | fuse_request_send_nowait(fc, req); | ||
511 | } | ||
512 | |||
494 | /* | 513 | /* |
495 | * Lock the request. Up to the next unlock_request() there mustn't be | 514 | * Lock the request. Up to the next unlock_request() there mustn't be |
496 | * anything that could cause a page-fault. If the request was already | 515 | * anything that could cause a page-fault. If the request was already |