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

Reply via email to