[SCM] Samba Shared Repository - branch master updated -
86cb14db2b041f6f78b7d5b6afe10d141c0b773d
Volker Lendecke
vlendec at samba.org
Mon Dec 29 12:19:33 GMT 2008
The branch, master has been updated
via 86cb14db2b041f6f78b7d5b6afe10d141c0b773d (commit)
via e4d28dbc040e186f453d77c7c1fb628a6cc2e3d4 (commit)
via afd70855b77aee4500b7d505419c750b6b2df38b (commit)
via 82a152fcf9254fe4189cac12fa3fc1744284ca13 (commit)
via 6251b97e02c890b184e13187020c19c8c2e82f2c (commit)
from 102028ec722d942d7f91eb92e8da4f1480d140d1 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 86cb14db2b041f6f78b7d5b6afe10d141c0b773d
Author: Volker Lendecke <vl at samba.org>
Date: Mon Dec 22 22:42:44 2008 +0100
Add code to test write_data_iov a bit
commit e4d28dbc040e186f453d77c7c1fb628a6cc2e3d4
Author: Volker Lendecke <vl at samba.org>
Date: Mon Dec 22 22:32:12 2008 +0100
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.
commit afd70855b77aee4500b7d505419c750b6b2df38b
Author: Volker Lendecke <vl at samba.org>
Date: Mon Dec 22 22:17:59 2008 +0100
Make write_data use write_data_iov
commit 82a152fcf9254fe4189cac12fa3fc1744284ca13
Author: Volker Lendecke <vl at samba.org>
Date: Mon Dec 22 22:17:28 2008 +0100
Add write_data_iov
commit 6251b97e02c890b184e13187020c19c8c2e82f2c
Author: Volker Lendecke <vl at samba.org>
Date: Sun Dec 21 23:22:30 2008 +0100
Add sys_writev
-----------------------------------------------------------------------
Summary of changes:
source3/include/proto.h | 2 +
source3/lib/system.c | 25 ++++++++++
source3/lib/util_sock.c | 115 +++++++++++++++++++++++++++++++++++---------
source3/libsmb/clientgen.c | 40 +++++----------
4 files changed, 132 insertions(+), 50 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 5a3776b..0826051 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -969,6 +969,7 @@ void *sys_memalign( size_t align, size_t size );
int sys_usleep(long usecs);
ssize_t sys_read(int fd, void *buf, size_t count);
ssize_t sys_write(int fd, const void *buf, size_t count);
+ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt);
ssize_t sys_pread(int fd, void *buf, size_t count, SMB_OFF_T off);
ssize_t sys_pwrite(int fd, const void *buf, size_t count, SMB_OFF_T off);
ssize_t sys_send(int s, const void *msg, size_t len, int flags);
@@ -1440,6 +1441,7 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
size_t *size_ret);
NTSTATUS read_data(int fd, char *buffer, size_t N);
ssize_t write_data(int fd, const char *buffer, size_t N);
+ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt);
bool send_keepalive(int client);
NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
unsigned int timeout,
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 86c4ef2..ed66666 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -142,6 +142,31 @@ ssize_t sys_write(int fd, const void *buf, size_t count)
}
/*******************************************************************
+A writev wrapper that will deal with EINTR.
+********************************************************************/
+
+ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ ssize_t ret;
+
+#if 0
+ /* Try to confuse write_data_iov a bit */
+ if ((random() % 5) == 0) {
+ return sys_write(fd, iov[0].iov_base, iov[0].iov_len);
+ }
+ if (iov[0].iov_len > 1) {
+ return sys_write(fd, iov[0].iov_base,
+ (random() % (iov[0].iov_len-1)) + 1);
+ }
+#endif
+
+ do {
+ ret = writev(fd, iov, iovcnt);
+ } while (ret == -1 && errno == EINTR);
+ return ret;
+}
+
+/*******************************************************************
A pread wrapper that will deal with EINTR and 64-bit file offsets.
********************************************************************/
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index 7fe8ed8..d23758a 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -635,40 +635,109 @@ NTSTATUS read_data(int fd, char *buffer, size_t N)
}
/****************************************************************************
- Write data to a fd.
+ Write all data from an iov array
****************************************************************************/
-ssize_t write_data(int fd, const char *buffer, size_t N)
+ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
{
- size_t total=0;
- ssize_t ret;
- char addr[INET6_ADDRSTRLEN];
+ int i;
+ size_t to_send;
+ ssize_t thistime;
+ size_t sent;
+ struct iovec *iov_copy, *iov;
- while (total < N) {
- ret = sys_write(fd,buffer + total,N - total);
+ to_send = 0;
+ for (i=0; i<iovcnt; i++) {
+ to_send += orig_iov[i].iov_len;
+ }
- if (ret == -1) {
- if (fd == get_client_fd()) {
- /* Try and give an error message saying
- * what client failed. */
- DEBUG(0,("write_data: write failure in "
- "writing to client %s. Error %s\n",
- get_peer_addr(fd,addr,sizeof(addr)),
- strerror(errno) ));
- } else {
- DEBUG(0,("write_data: write failure. "
- "Error = %s\n", strerror(errno) ));
+ thistime = sys_writev(fd, orig_iov, iovcnt);
+ if ((thistime <= 0) || (thistime == to_send)) {
+ return thistime;
+ }
+ sent = thistime;
+
+ /*
+ * We could not send everything in one call. Make a copy of iov that
+ * we can mess with. We keep a copy of the array start in iov_copy for
+ * the TALLOC_FREE, because we're going to modify iov later on,
+ * discarding elements.
+ */
+
+ iov_copy = (struct iovec *)TALLOC_MEMDUP(
+ talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
+
+ if (iov_copy == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ iov = iov_copy;
+
+ while (sent < to_send) {
+ /*
+ * We have to discard "thistime" bytes from the beginning
+ * iov array, "thistime" contains the number of bytes sent
+ * via writev last.
+ */
+ while (thistime > 0) {
+ if (thistime < iov[0].iov_len) {
+ char *new_base =
+ (char *)iov[0].iov_base + thistime;
+ iov[0].iov_base = new_base;
+ iov[0].iov_len -= thistime;
+ break;
}
- return -1;
+ thistime -= iov[0].iov_len;
+ iov += 1;
+ iovcnt -= 1;
}
- if (ret == 0) {
- return total;
+ thistime = sys_writev(fd, iov, iovcnt);
+ if (thistime <= 0) {
+ break;
}
+ sent += thistime;
+ }
+
+ TALLOC_FREE(iov_copy);
+ return sent;
+}
+
+/****************************************************************************
+ Write data to a fd.
+****************************************************************************/
+
+/****************************************************************************
+ Write data to a fd.
+****************************************************************************/
- total += ret;
+ssize_t write_data(int fd, const char *buffer, size_t N)
+{
+ ssize_t ret;
+ struct iovec iov;
+
+ iov.iov_base = CONST_DISCARD(char *, buffer);
+ iov.iov_len = N;
+
+ ret = write_data_iov(fd, &iov, 1);
+ if (ret >= 0) {
+ return ret;
}
- return (ssize_t)total;
+
+ if (fd == get_client_fd()) {
+ char addr[INET6_ADDRSTRLEN];
+ /*
+ * Try and give an error message saying what client failed.
+ */
+ DEBUG(0, ("write_data: write failure in writing to client %s. "
+ "Error %s\n", get_peer_addr(fd,addr,sizeof(addr)),
+ strerror(errno)));
+ } else {
+ DEBUG(0,("write_data: write failure. Error = %s\n",
+ strerror(errno) ));
+ }
+
+ return -1;
}
/****************************************************************************
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index ff01b67..fd5627d 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/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 at 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. */
--
Samba Shared Repository
More information about the samba-cvs
mailing list