diff options
author | Volker Lendecke <vl@samba.org> | 2008-12-23 22:45:03 +0100 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2008-12-31 19:33:25 +0100 |
commit | e0fd61f0cbfb0a25c8e9603375c2eb98936c8345 (patch) | |
tree | d285caeb919585de2f84d1492172f7e0d93d97cc /source3 | |
parent | 9e1cabdd43bb608c6aa707f0e42d99e204e86603 (diff) | |
download | samba-e0fd61f0cbfb0a25c8e9603375c2eb98936c8345.tar.gz samba-e0fd61f0cbfb0a25c8e9603375c2eb98936c8345.tar.bz2 samba-e0fd61f0cbfb0a25c8e9603375c2eb98936c8345.zip |
Try to fix recvfile using splice on Linux
According to the splice(2) manpage, one of the file descriptors *must* be a
pipe. With this patch I could successfully run splice(2) on a debian lenny
installation.
Jeremy, please check!
Diffstat (limited to 'source3')
-rw-r--r-- | source3/lib/recvfile.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index 513742ce8f..41f7213943 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -145,6 +145,7 @@ ssize_t sys_recvfile(int fromfd, SMB_OFF_T offset, size_t count) { + static int pipefd[2] = { -1, -1 }; static bool try_splice_call = true; size_t total_written = 0; @@ -171,31 +172,45 @@ ssize_t sys_recvfile(int fromfd, count); } - while (total_written < count) { - ssize_t ret = splice(fromfd, - NULL, - tofd, - &offset, - count, - 0); - if (ret == -1) { - if (errno != EINTR) { - if (total_written == 0 && - (errno == EBADF || errno == EINVAL)) { - try_splice_call = false; - return default_sys_recvfile(fromfd, - tofd, - offset, - count); - } - break; + if ((pipefd[0] == -1) && (pipe(pipefd) == -1)) { + try_splice_call = false; + return default_sys_recvfile(fromfd, tofd, offset, count); + } + + while (count > 0) { + int nread, to_write; + + nread = splice(fromfd, NULL, pipefd[1], NULL, count, 0); + if (nread == -1) { + if (errno == EINTR) { + continue; + } + if (total_written == 0 && + (errno == EBADF || errno == EINVAL)) { + try_splice_call = false; + return default_sys_recvfile(fromfd, tofd, + offset, count); } - continue; + break; } - total_written += ret; - count -= ret; + + to_write = nread; + while (to_write > 0) { + int thistime; + thistime = splice(pipefd[0], NULL, tofd, &offset, + to_write, 0); + if (thistime == -1) { + goto done; + } + offset += thistime; + to_write -= thistime; + } + + total_written += nread; + count -= nread; } + done: if (total_written < count) { int saved_errno = errno; if (drain_socket(fromfd, count-total_written) != |