Replace FUSE_MAX_PAGES_PER_REQ with the configurable parameter max_pages to improve performance. Old RFC with detailed description of the problem and many fixes by Mitsuo Hayasaka (mitsuo.hayasaka.hu@hitachi.com): - https://lkml.org/lkml/2012/7/5/136 We've encountered performance degradation and fixed it on a big and complex virtual environment. Environment to reproduce degradation and improvement: 1. Add lag to user mode FUSE Add nanosleep(&(struct timespec){ 0, 1000 }, NULL); to xmp_write_buf in passthrough_fh.c 2. patch UM fuse with configurable max_pages parameter. The patch will be provided latter. 3. run test script and perform test on tmpfs fuse_test() { cd /tmp mkdir -p fusemnt passthrough_fh -o max_pages=$1 /tmp/fusemnt grep fuse /proc/self/mounts dd conv=fdatasync oflag=dsync if=/dev/zero of=fusemnt/tmp/tmp \ count=1K bs=1M 2>&1 | grep -v records rm fusemnt/tmp/tmp killall passthrough_fh } Test results: passthrough_fh /tmp/fusemnt fuse.passthrough_fh \ rw,nosuid,nodev,relatime,user_id=0,group_id=0 0 0 1073741824 bytes (1.1 GB) copied, 1.73867 s, 618 MB/s passthrough_fh /tmp/fusemnt fuse.passthrough_fh \ rw,nosuid,nodev,relatime,user_id=0,group_id=0,max_pages=256 0 0 1073741824 bytes (1.1 GB) copied, 1.15643 s, 928 MB/s Obviously with bigger lag the difference between 'before' and 'after' will be more significant. Mitsuo Hayasaka, in 2012 (https://lkml.org/lkml/2012/7/5/136), observed improvement from 400-550 to 520-740.
Showing the changes to include/uapi/linux (1 of 5 files). Show all
Unified · Split
| @@ -120,6 +120,7 @@ · 119 unmodified lines | ||
| 120 | 120 | * 7.28 |
| 121 | 121 | * - add FUSE_COPY_FILE_RANGE |
| 122 | 122 | * - add FOPEN_CACHE_DIR |
| 123 | + * - add FUSE_MAX_PAGES, add max_pages to init_out | |
| 123 | 124 | */ |
| 124 | 125 | |
| 125 | 126 | #ifndef _LINUX_FUSE_H |
| @@ -255,6 +256,7 @@ struct fuse_file_lock { · 129 unmodified lines | ||
| 255 | 256 | * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc |
| 256 | 257 | * FUSE_POSIX_ACL: filesystem supports posix acls |
| 257 | 258 | * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED |
| 259 | + * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages | |
| 258 | 260 | */ |
| 259 | 261 | #define FUSE_ASYNC_READ (1 << 0) |
| 260 | 262 | #define FUSE_POSIX_LOCKS (1 << 1) |
| @@ -278,6 +280,7 @@ struct fuse_file_lock { · 17 unmodified lines | ||
| 278 | 280 | #define FUSE_HANDLE_KILLPRIV (1 << 19) |
| 279 | 281 | #define FUSE_POSIX_ACL (1 << 20) |
| 280 | 282 | #define FUSE_ABORT_ERROR (1 << 21) |
| 283 | +#define FUSE_MAX_PAGES (1 << 22) | |
| 281 | 284 | |
| 282 | 285 | /** |
| 283 | 286 | * CUSE INIT request/reply flags |
| @@ -617,7 +620,9 @@ struct fuse_init_out { · 333 unmodified lines | ||
| 617 | 620 | uint16_t congestion_threshold; |
| 618 | 621 | uint32_t max_write; |
| 619 | 622 | uint32_t time_gran; |
| 620 | − uint32_t unused[9]; | |
| 623 | + uint16_t max_pages; | |
| 624 | + uint16_t padding; | |
| 625 | + uint32_t unused[8]; | |
| 621 | 626 | }; |
| 622 | 627 | |
| 623 | 628 | #define CUSE_INIT_INFO_MAX 4096 |