X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Flib%2Frecvfile.c;h=ea0159642137390a0f7e57a123684e6e63e47581;hb=8905b599b467f0595cf5874b7e36d9a650f8544a;hp=513742ce8f8edfa298ab3f0721fe85588d55ebd2;hpb=9d3d3320928e43a972b88024a52986331d0dbee0;p=ira%2Fwip.git diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index 513742ce8f8..ea015964213 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -145,8 +145,10 @@ ssize_t sys_recvfile(int fromfd, SMB_OFF_T offset, size_t count) { - static bool try_splice_call = true; + static int pipefd[2] = { -1, -1 }; + static bool try_splice_call = false; size_t total_written = 0; + loff_t splice_offset = offset; DEBUG(10,("sys_recvfile: from = %d, to = %d, " "offset=%.0f, count = %lu\n", @@ -171,31 +173,46 @@ 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, + MIN(count, 16384), SPLICE_F_MOVE); + 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, + &splice_offset, to_write, + SPLICE_F_MOVE); + if (thistime == -1) { + goto done; + } + to_write -= thistime; + } + + total_written += nread; + count -= nread; } + done: if (total_written < count) { int saved_errno = errno; if (drain_socket(fromfd, count-total_written) !=