From 592000c0f937588d020cda4d2841e84cb5d977ba Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Wed, 11 Mar 2015 14:24:46 -0400 Subject: [PATCH] Increase Linux pipe buffer on zfs recv size to the maximum system size I noticed when reviewing documentation that it is possible for userspace to use fctnl(fd, F_SETPIPE_SZ, (unsigned long) size) to change the kernel pipe buffer size on Linux to increase the pipe size up to the value specified in /proc/sys/fs/pipe-max-size. We have people using mbuffer to improve zfs recv performance when piping over the network, so it seems advantageous to integrate such functionality directly into the zfs recv tool. This could have been configurable or we could have changed the value back to the original (had we read it) after we were done with the file descriptor,but I do not see a strong case for doing either, so I went with a simple implementation. Closes zfsonlinux/zfs#1161 Signed-off-by: Richard Yao --- lib/libzfs/libzfs_sendrecv.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index e3572914c997..15fc2d2bafed 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -3293,11 +3294,33 @@ int zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t *flags, int infd, avl_tree_t *stream_avl) { + struct stat sb; char *top_zfs = NULL; int err; int cleanup_fd; uint64_t action_handle = 0; + if (fstat(infd, &sb) == -1) { + perror("fstat"); + return (-2); + } + + /* + * It is not uncommon for gigabytes to be processed in zfs receive. + * Speculatively increase the buffer size via Linux-specific fcntl() + * call. + */ + if (S_ISFIFO(sb.st_mode)) { + FILE *procf = fopen("/proc/sys/fs/pipe-max-size", "r"); + + if (procf != NULL) { + unsigned long pipe_max_size; + fscanf(procf, "%lu", &pipe_max_size); + (void) fcntl(infd, F_SETPIPE_SZ, pipe_max_size); + fclose(procf); + } + } + cleanup_fd = open(ZFS_DEV, O_RDWR); VERIFY(cleanup_fd >= 0);