Attempt to fix bug 5953: Make cli_send_smb_direct_writeX use writev
authorVolker Lendecke <vl@samba.org>
Mon, 22 Dec 2008 21:32:12 +0000 (22:32 +0100)
committerVolker Lendecke <vl@samba.org>
Mon, 29 Dec 2008 11:12:59 +0000 (12:12 +0100)
It seems there are SMB servers around which can't cope with the write header
being sent in a packet of its own. With writev we keep the advantage of direct
writes, giving the kernel the chance to coalesce the write calls.

source/libsmb/clientgen.c

index d6d26e41a69adc012cf55c979f1d2f4937a19eba..aeb1c282daef2fc3fd24b130df34806cdab2073a 100644 (file)
@@ -315,7 +315,7 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli,
        /* First length to send is the offset to the data. */
        size_t len = SVAL(cli->outbuf,smb_vwv11) + 4;
        size_t nwritten=0;
-       ssize_t ret;
+       struct iovec iov[2];
 
        /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
        if (cli->fd == -1) {
@@ -327,33 +327,19 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli,
                return false;
        }
 
-       while (nwritten < len) {
-               ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
-               if (ret <= 0) {
-                       close(cli->fd);
-                       cli->fd = -1;
-                       cli->smb_rw_error = SMB_WRITE_ERROR;
-                       DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
-                               (int)len,(int)ret, strerror(errno) ));
-                       return false;
-               }
-               nwritten += ret;
-       }
+       iov[0].iov_base = cli->outbuf;
+       iov[0].iov_len = len;
+       iov[1].iov_base = CONST_DISCARD(char *, p);
+       iov[1].iov_len = extradata;
 
-       /* Now write the extra data. */
-       nwritten=0;
-       while (nwritten < extradata) {
-               ret = write_socket(cli->fd,p+nwritten,extradata - nwritten);
-               if (ret <= 0) {
-                       close(cli->fd);
-                       cli->fd = -1;
-                       cli->smb_rw_error = SMB_WRITE_ERROR;
-                       DEBUG(0,("Error writing %d extradata "
-                               "bytes to client. %d (%s)\n",
-                               (int)extradata,(int)ret, strerror(errno) ));
-                       return false;
-               }
-               nwritten += ret;
+       nwritten = write_data_iov(cli->fd, iov, 2);
+       if (nwritten < (len + extradata)) {
+               close(cli->fd);
+               cli->fd = -1;
+               cli->smb_rw_error = SMB_WRITE_ERROR;
+               DEBUG(0,("Error writing %d bytes to client. (%s)\n",
+                        (int)(len+extradata), strerror(errno)));
+               return false;
        }
 
        /* Increment the mid so we can tell between responses. */