From 250a556b1e3eb8486ec294f94d3b918c9ac91542 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 2 Dec 2011 17:13:49 +0100 Subject: Make solaris use sendfilev sendfilev is a richer API which allows us to do non blocking TCP on solaris. The normal sendfile API seems to have some issue with non blocking sockets and the return value of sendfile. --- erts/emulator/drivers/unix/unix_efile.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'erts/emulator/drivers/unix/unix_efile.c') diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 72911641d3..2b68334ad7 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1488,7 +1488,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, off_t *offset, Uint64 *nbytes, struct t_sendfile_hdtl* hdtl) { Uint64 written = 0; -#if defined(__linux__) || (defined(__sun) && defined(__SVR4)) +#if defined(__linux__) ssize_t retval; do { // check if *nbytes is 0 or greater than the largest size_t @@ -1503,6 +1503,28 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, } while (retval != -1 && retval == SENDFILE_CHUNK_SIZE); *nbytes = written; return check_error(retval == -1 ? -1 : 0, errInfo); +#elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) + ssize_t retval; + size_t len; + sendfilevec_t fdrec; + fdrec.sfv_fd = in_fd; + fdrec.sfv_flag = SFV_NOWAIT; + do { + fdrec.sfv_off = *offset; + len = 0; + if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) + fdrec.sfv_len = SENDFILE_CHUNK_SIZE; + else + fdrec.sfv_len = *nbytes; + retval = sendfilev(out_fd, &fdrec, 1, &len); + if (retval != -1 || errno == EAGAIN || errno == EINTR) { + *offset += len; + *nbytes -= len; + written += len; + } + } while (len == SENDFILE_CHUNK_SIZE); + *nbytes = written; + return check_error(retval == -1 ? -1 : 0, errInfo); #elif defined(DARWIN) int retval; off_t len; -- cgit v1.2.3 From ec885e883c99825e7d737752b1b0aebbbafbd670 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 5 Dec 2011 18:45:44 +0100 Subject: Clarify some code comments Thanks Tuncer Ayaz --- erts/emulator/drivers/unix/unix_efile.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'erts/emulator/drivers/unix/unix_efile.c') diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 2b68334ad7..92314fce36 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1469,6 +1469,9 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, } #ifdef HAVE_SENDFILE + +// For some reason the maximum size_t cannot be used as the max size +// 3GB seems to work on all platforms #define SENDFILE_CHUNK_SIZE ((1 << 30) -1) /* @@ -1477,7 +1480,13 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, * we have to emulate some things in linux and play with variables on * bsd/darwin. * - * It could be possible to implement header/trailer in sendfile, though + * All of the calls will split a command which tries to send more than + * SENDFILE_CHUNK_SIZE of data at once. + * + * On platforms where *nbytes of 0 does not mean the entire file, this is + * simulated. + * + * It could be possible to implement header/trailer in sendfile. Though * you would have to emulate it in linux and on BSD/Darwin some complex * calculations have to be made when using a non blocking socket to figure * out how much of the header/file/trailer was sent in each command. @@ -1491,7 +1500,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, #if defined(__linux__) ssize_t retval; do { - // check if *nbytes is 0 or greater than the largest size_t + // check if *nbytes is 0 or greater than chunk size if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) retval = sendfile(out_fd, in_fd, offset, SENDFILE_CHUNK_SIZE); else @@ -1512,6 +1521,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, do { fdrec.sfv_off = *offset; len = 0; + // check if *nbytes is 0 or greater than chunk size if (*nbytes == 0 || *nbytes > SENDFILE_CHUNK_SIZE) fdrec.sfv_len = SENDFILE_CHUNK_SIZE; else @@ -1529,7 +1539,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, int retval; off_t len; do { - // check if *nbytes is 0 or greater than the largest off_t + // check if *nbytes is 0 or greater than chunk size if(*nbytes > SENDFILE_CHUNK_SIZE) len = SENDFILE_CHUNK_SIZE; else -- cgit v1.2.3 From f34a89e0c0cc92226d5fe3fb257c62251068392b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 7 Dec 2011 10:46:22 +0100 Subject: Do not use SFV_NOWAIT as it does not exist on all solaris --- erts/emulator/drivers/unix/unix_efile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/emulator/drivers/unix/unix_efile.c') diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 92314fce36..630c570f7c 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1517,7 +1517,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, size_t len; sendfilevec_t fdrec; fdrec.sfv_fd = in_fd; - fdrec.sfv_flag = SFV_NOWAIT; + fdrec.sfv_flag = 0; do { fdrec.sfv_off = *offset; len = 0; -- cgit v1.2.3