Messages in this thread | | | Date | Thu, 8 Jan 2009 11:13:51 +0100 | From | Volker Lendecke <> | Subject | maximum buffer size for splice(2) tcp->pipe? |
| |
Hi!
While implementing splice support in Samba for better performance I found it blocking when trying to pull data off tcp into a pipe when the recvq was full. Attached find a test program that shows this behaviour, on another host I started
netcat 192.168.19.10 4711 < /dev/zero
vlendec@lenny:~$ uname -a Linux lenny 2.6.28-06857-g5cbd04a #7 Wed Jan 7 10:10:42 CET 2009 x86_64 = GNU/Linux vlendec@lenny:~$ gcc -o splicetest /host/home/vlendec/splicetest.c -O3 -Wall vlendec@lenny:~$ ./splicetest out 65536 & [1] 697 vlendec@lenny:~$ strace -p 697 Process 697 attached - interrupt to quit splice(0x3, 0, 0x5, 0, 0x56a0, 0x1) = 22176 splice(0x7, 0, 0x4, 0, 0x10000, 0x1^C <unfinished ...> Process 697 detached vlendec@lenny:~$ netstat -nt | grep 4711 tcp 69272 0 192.168.19.10:4711 192.168.19.1:33773 ESTABLISHED vlendec@lenny:~$
Interestingly, whenever I start the strace, it gets another chunk of data and then blocks in the next splice call.
If I start splicetest with a buffer size of 16384 instead of 65536, it does not block. I could not find a way to ask the kernel for the tipping point below which it does not block.
What is a safe buffer size to use with splice?
BTW, this kernel is from Steve French's linux-cifs.git repo.
Thanks,
Volker Lendecke
Samba Team
P.S: I'm not subscribed to linux-kernel, so if possible please CC me directly. If this is inappropriate behaviour, please give me a quick hint :-)
-- SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen phone: +49-551-370000-0, fax: +49-551-370000-9 AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen #define _GNU_SOURCE #include <fcntl.h>
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
int main(int argc, const char *argv[]) { int pipefds[2]; int file_fd; int sock; int listen_fd; struct sockaddr_in in_addr; int res; int to_read;
if (argc != 3) { fprintf(stderr, "usage: %s <filename> to_read\n", argv[0]); exit(1); }
to_read = atoi(argv[2]);
if (pipe(pipefds) != 0) { fprintf(stderr, "pipe returned %s\n", strerror(errno)); exit(1); }
if ((file_fd = open(argv[1], O_CREAT|O_RDWR, 0644)) == -1) { fprintf(stderr, "open returned %s\n", strerror(errno)); exit(1); }
listen_fd = socket(PF_INET, SOCK_STREAM, 0); if (listen_fd == -1) { fprintf(stderr, "socket returned %s\n", strerror(errno)); exit(1); }
in_addr.sin_family = AF_INET; inet_aton("0.0.0.0", &in_addr.sin_addr); in_addr.sin_port = htons(4711);
res = bind(listen_fd, (struct sockaddr *)&in_addr, sizeof(in_addr)); if (res == -1) { fprintf(stderr, "bind returned %s\n", strerror(errno)); exit(1); }
res = listen(listen_fd, 5); if (res == -1) { fprintf(stderr, "listen returned %s\n", strerror(errno)); exit(1); }
sock = accept(listen_fd, NULL, NULL); if (sock == -1) { fprintf(stderr, "accept returned %s\n", strerror(errno)); exit(1); }
while (1) { ssize_t nread, nwritten;
nread = splice(sock, NULL, pipefds[1], NULL, to_read, SPLICE_F_MOVE); if (nread == -1) { fprintf(stderr, "splice failed: %s\n", strerror(errno)); exit(1); }
if (nread == 0) { printf("EOF\n"); return 0; }
nwritten = splice(pipefds[0], NULL, file_fd, NULL, nread, SPLICE_F_MOVE); if (nwritten != nread) { fprintf(stderr, "splice failed: %d/%d %s\n", (int)nread, (int)nwritten, nwritten == -1 ? strerror(errno) : ""); exit(1); } }
return 0; } [unhandled content-type:application/pgp-signature] | |