From: Volker Lendecke Date: Mon, 22 Dec 2008 21:32:12 +0000 (+0100) Subject: Attempt to fix bug 5953: Make cli_send_smb_direct_writeX use writev X-Git-Tag: samba-3.3.0~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c7f4b26bc038ad949c81f77a57cc709b4d144f7;p=thirdparty%2Fsamba.git Attempt to fix bug 5953: Make cli_send_smb_direct_writeX use writev 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. (cherry picked from commit 1cbe293e7ba16968bf0e106cb6ee723a1f31d5bb) --- diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index 2c0950de03a..b51eb479709 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -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. */