The branch, master has been updated via 4daf7d4 libs: s3 and s4: make our dns lookup code signal-safe. via f5a3d74 s3: smbd: Performance optimization for RECVFILE. from 88ba811 s4-wbclient: Fix wbc_sids_to_xids to correctly indicate the length of the SID list
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 4daf7d475c8cca69e2e3b20dc9fb84c4bd8cb4cb Author: Jeremy Allison <j...@samba.org> Date: Wed Apr 9 15:27:45 2014 -0700 libs: s3 and s4: make our dns lookup code signal-safe. Cope with -1,EINTR returns. Needed as this code can be called from inside smbd. Also fixes a bug in not checking the return from poll() correctly. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Kai Blin <k...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Thu Apr 10 22:06:08 CEST 2014 on sn-devel-104 commit f5a3d74264abb25009e73b1b35d62db34fa62343 Author: Jeremy Allison <j...@samba.org> Date: Wed Apr 9 09:50:46 2014 -0700 s3: smbd: Performance optimization for RECVFILE. Based on work proposed by Jones <jones.k...@gmail.com>. Removes set_blocking()/set_unblocking() fcntl calls around RECVFILE on the non-blocking socket. Instead uses RECVFILE in a loop, and only drops back to set_blocking()/set_unblocking() once RECVFILE returns -1/EAGAIN/EWOULDBLOCK. From the samba-technical list: ------------------------------------------------ The iometer 512b sequential write shows following result, Before applying this patch: 75333 IOps After applying this patch: 82691 IOps ------------------------------------------------ Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/addns/dnssock.c | 29 +++++++++++++++++++++---- source3/smbd/vfs.c | 56 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 18 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/addns/dnssock.c b/lib/addns/dnssock.c index 5f99519..13649b5 100644 --- a/lib/addns/dnssock.c +++ b/lib/addns/dnssock.c @@ -70,7 +70,9 @@ static DNS_ERROR dns_tcp_open( const char *nameserver, s_in.sin_addr.s_addr = ulAddress; s_in.sin_port = htons( DNS_TCP_PORT ); - res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in )); + do { + res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in )); + } while ((res == -1) && (errno == EINTR)); if (res == -1) { TALLOC_FREE(conn); return ERROR_DNS_CONNECTION_FAILED; @@ -155,7 +157,11 @@ static DNS_ERROR write_all(int fd, uint8_t *data, size_t len) while (total < len) { - ssize_t ret = write(fd, data + total, len - total); + ssize_t ret; + + do { + ret = write(fd, data + total, len - total); + } while ((ret == -1) && (errno == EINTR)); if (ret <= 0) { /* @@ -187,9 +193,11 @@ static DNS_ERROR dns_send_udp(struct dns_connection *conn, { ssize_t ret; - ret = sendto(conn->s, buf->data, buf->offset, 0, + do { + ret = sendto(conn->s, buf->data, buf->offset, 0, (struct sockaddr *)&conn->RecvAddr, sizeof(conn->RecvAddr)); + } while ((ret == -1) && (errno == EINTR)); if (ret != buf->offset) { return ERROR_DNS_SOCKET_ERROR; @@ -225,12 +233,21 @@ static DNS_ERROR read_all(int fd, uint8_t *data, size_t len) pfd.events = POLLIN|POLLHUP; fd_ready = poll(&pfd, 1, 10000); + if (fd_ready == -1) { + if (errno == EINTR) { + continue; + } + return ERROR_DNS_SOCKET_ERROR; + } if ( fd_ready == 0 ) { /* read timeout */ return ERROR_DNS_SOCKET_ERROR; } - ret = read(fd, data + total, len - total); + do { + ret = read(fd, data + total, len - total); + } while ((ret == -1) && (errno == EINTR)); + if (ret <= 0) { /* EOF or error */ return ERROR_DNS_SOCKET_ERROR; @@ -300,7 +317,9 @@ static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx, return ERROR_DNS_NO_MEMORY; } - received = recv(conn->s, (void *)buf->data, 512, 0); + do { + received = recv(conn->s, (void *)buf->data, 512, 0); + } while ((received == -1) && (errno == EINTR)); if (received == -1) { TALLOC_FREE(buf); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index bc9157a..897bf1f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -473,24 +473,54 @@ ssize_t vfs_pwrite_data(struct smb_request *req, if (req && req->unread_bytes) { int sockfd = req->sconn->sock; - int old_flags; SMB_ASSERT(req->unread_bytes == N); /* VFS_RECVFILE must drain the socket * before returning. */ req->unread_bytes = 0; - /* Ensure the socket is blocking. */ - old_flags = fcntl(sockfd, F_GETFL, 0); - if (set_blocking(sockfd, true) == -1) { - return (ssize_t)-1; - } - ret = SMB_VFS_RECVFILE(sockfd, - fsp, - offset, - N); - if (fcntl(sockfd, F_SETFL, old_flags) == -1) { - return (ssize_t)-1; + /* + * Leave the socket non-blocking and + * use SMB_VFS_RECVFILE. If it returns + * EAGAIN || EWOULDBLOCK temporarily set + * the socket blocking and retry + * the RECVFILE. + */ + while (total < N) { + ret = SMB_VFS_RECVFILE(sockfd, + fsp, + offset + total, + N - total); +#if defined(EWOULDBLOCK) + if (ret == 0 || (ret == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK))) { +#else /* EWOULDBLOCK */ + if (ret == 0 || (ret == -1 && errno == EAGAIN)) { +#endif /* EWOULDBLOCK */ + int old_flags; + /* Ensure the socket is blocking. */ + old_flags = fcntl(sockfd, F_GETFL, 0); + if (set_blocking(sockfd, true) == -1) { + return (ssize_t)-1; + } + ret = SMB_VFS_RECVFILE(sockfd, + fsp, + offset + total, + N - total); + if (fcntl(sockfd, F_SETFL, old_flags) == -1) { + return (ssize_t)-1; + } + if (ret == -1) { + return (ssize_t)-1; + } + total += ret; + return (ssize_t)total; + } + /* Any other error case. */ + if (ret == -1) { + return ret; + } + total += ret; } - return ret; + return (ssize_t)total; } while (total < N) { -- Samba Shared Repository