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 /include/uapi | |
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 'include/uapi')
-rw-r--r-- | include/uapi/linux/fuse.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index d8c713e148e3..5dc1fea49ecd 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h | |||
@@ -193,6 +193,7 @@ struct fuse_file_lock { | |||
193 | #define FUSE_FLOCK_LOCKS (1 << 10) | 193 | #define FUSE_FLOCK_LOCKS (1 << 10) |
194 | #define FUSE_HAS_IOCTL_DIR (1 << 11) | 194 | #define FUSE_HAS_IOCTL_DIR (1 << 11) |
195 | #define FUSE_AUTO_INVAL_DATA (1 << 12) | 195 | #define FUSE_AUTO_INVAL_DATA (1 << 12) |
196 | #define FUSE_DO_READDIRPLUS (1 << 13) | ||
196 | 197 | ||
197 | /** | 198 | /** |
198 | * CUSE INIT request/reply flags | 199 | * CUSE INIT request/reply flags |
@@ -299,6 +300,7 @@ enum fuse_opcode { | |||
299 | FUSE_NOTIFY_REPLY = 41, | 300 | FUSE_NOTIFY_REPLY = 41, |
300 | FUSE_BATCH_FORGET = 42, | 301 | FUSE_BATCH_FORGET = 42, |
301 | FUSE_FALLOCATE = 43, | 302 | FUSE_FALLOCATE = 43, |
303 | FUSE_READDIRPLUS = 44, | ||
302 | 304 | ||
303 | /* CUSE specific operations */ | 305 | /* CUSE specific operations */ |
304 | CUSE_INIT = 4096, | 306 | CUSE_INIT = 4096, |
@@ -630,6 +632,16 @@ struct fuse_dirent { | |||
630 | #define FUSE_DIRENT_SIZE(d) \ | 632 | #define FUSE_DIRENT_SIZE(d) \ |
631 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) | 633 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) |
632 | 634 | ||
635 | struct fuse_direntplus { | ||
636 | struct fuse_entry_out entry_out; | ||
637 | struct fuse_dirent dirent; | ||
638 | }; | ||
639 | |||
640 | #define FUSE_NAME_OFFSET_DIRENTPLUS \ | ||
641 | offsetof(struct fuse_direntplus, dirent.name) | ||
642 | #define FUSE_DIRENTPLUS_SIZE(d) \ | ||
643 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen) | ||
644 | |||
633 | struct fuse_notify_inval_inode_out { | 645 | struct fuse_notify_inval_inode_out { |
634 | __u64 ino; | 646 | __u64 ino; |
635 | __s64 off; | 647 | __s64 off; |