fix to util_sock.c

okuyamak at dd.iij4u.or.jp okuyamak at dd.iij4u.or.jp
Sun Nov 12 12:56:57 GMT 2000


Dear all,

I don't think I can keep my promise (^^;). I found something
interesting in different part, which is easier to fix.


I've made fix against HEAD branch of ./source/lib/util_sock.c.
# Since this file is not being changed since 2.0.7, this also works
# for 2.0.7 or 2.2 as well.

Here's what I did.

1) Created new global function socket_read().
  Since SSL_read() and read() calling stuff is spread all over,
  I decided to make this into single function.

2) Instead of calling read() even for usual cases, I changed
   it to use recv().

3) socket_read() have 'flags' option, which is passed to recv().
   Also, when this function is called from read_socket_data()
  and read_data(), option MSG_WAITALL is passed.

   If your system supports MSG_WAITALL, recv() will not return
  until required length of data is recieved entirely ( and if
  you look at read_data() and read_socket_data(), you'll see
  that's what you really requested for ).

  If MSG_WAITALL is not being supported, configure will set
  MSG_WAITALL to 0, so this will not take effect, and will work
  exactly like original code ( except for recv() being called
  instead of read() ).


This patch will not make samba FAST(*), but this will make samba
slightly LIGHER, for change made by 3 will prevent context switch
between user(smbd) and kernel mode.

When I counted system call using same netbench, original called
read() against socket over 500ktimes, but this code only calls
recv() 370ktimes now. CPU power being reduced, will be passed to
kernel, and make kernel to work more better ( stable usually ).

*) The reason why this will not make samba fast, is because
  this routine will NOT speed up receiving. We can only receive
  packet at speed of media. So if SMBrequest was 5000bytes,
  This usually requiers 4 IP packets on ethernet. This is usually
  somewhat around 48000bits which takes 480usec on 100Mbps ethernet
  with FULL RATE, so no matter how fast CPU may be, we can't go
  forward until we recieve all data.

   We have no way to speed up the receiving, so, what we can do
  against recieve phase is
  i ) let's do whatever we can using information given from
    first packet. This means, don't recieve entire packet at first
    phase. But this requires large change.
  ii) let's leave all the receiving to kernel by passing 
    MSG_WAITALL flag, whenever we can.

  If you found that your server became faster with this patch,
  it means your server is overloaded. You need more faster
  CPU for server.


Testing this function is very easy. If you can't communicate between
client using this patch, then something is wrong ( but I'm writing
this mail on Windows machine, and made following patch against
source code on Linux machine using samba I patched. So, I don't
think there's any big problem. If problem occured... I think that's
because somebody is calling this socket_read() against non-socket
file descriptor, which we shouldn't ).


best regards,
---- 
Kenichi Okuyama at Tokyo Research Lab, IBM-Japan, Co.

and here comes the patch:


--- samba-2.2.orig/source/lib/util_sock.c	Sat Oct  7 06:12:25 2000
+++ samba-2.2/source/lib/util_sock.c	Sun Nov 12 20:40:53 2000
@@ -222,15 +222,7 @@
     if (mincnt == 0) mincnt = maxcnt;
 
     while (nread < mincnt) {
-#ifdef WITH_SSL
-      if(fd == sslFd){
-        readret = SSL_read(ssl, buf + nread, maxcnt - nread);
-      }else{
-        readret = read(fd, buf + nread, maxcnt - nread);
-      }
-#else /* WITH_SSL */
-      readret = read(fd, buf + nread, maxcnt - nread);
-#endif /* WITH_SSL */
+        readret	= socket_read( fd, buf + nread, maxcnt - nread, 0 );
 
       if (readret == 0) {
         DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
@@ -279,15 +271,7 @@
       return -1;
     }
       
-#ifdef WITH_SSL
-    if(fd == sslFd){
-      readret = SSL_read(ssl, buf + nread, maxcnt - nread);
-    }else{
-      readret = read(fd, buf + nread, maxcnt - nread);
-    }
-#else /* WITH_SSL */
-    readret = read(fd, buf+nread, maxcnt-nread);
-#endif /* WITH_SSL */
+    readret	= socket_read( fd, buf + nread, maxcnt - nread, 0 );
 
     if (readret == 0) {
       /* we got EOF on the file descriptor */
@@ -334,15 +318,7 @@
     if (mincnt == 0) mincnt = maxcnt;
 
     while (nread < mincnt) {
-#ifdef WITH_SSL
-      if(fd == sslFd){
-        readret = SSL_read(ssl, buf + nread, maxcnt - nread);
-      }else{
-        readret = read(fd, buf + nread, maxcnt - nread);
-      }
-#else /* WITH_SSL */
-      readret = read(fd, buf + nread, maxcnt - nread);
-#endif /* WITH_SSL */
+        readret	= socket_read( fd, buf + nread, maxcnt - nread, 0 );
 
       if (readret <= 0)
 	return readret;
@@ -371,15 +347,7 @@
     if(selrtn <= 0)
       return selrtn;
       
-#ifdef WITH_SSL
-    if(fd == sslFd){
-      readret = SSL_read(ssl, buf + nread, maxcnt - nread);
-    }else{
-      readret = read(fd, buf + nread, maxcnt - nread);
-    }
-#else /* WITH_SSL */
-    readret = read(fd, buf+nread, maxcnt-nread);
-#endif /* WITH_SSL */
+    readret	= socket_read( fd, buf + nread, maxcnt - nread, 0 );
 
     if (readret <= 0)
       return readret;
@@ -418,15 +386,7 @@
 
   while (total < N)
   {
-#ifdef WITH_SSL
-    if(fd == sslFd){
-      ret = SSL_read(ssl, buffer + total, N - total);
-    }else{
-      ret = read(fd,buffer + total,N - total);
-    }
-#else /* WITH_SSL */
-    ret = read(fd,buffer + total,N - total);
-#endif /* WITH_SSL */
+      ret	= socket_read( fd, buffer + total, N - total, MSG_WAITALL );
 
     if (ret == 0)
     {
@@ -458,15 +418,7 @@
 
   while (total < N)
   {
-#ifdef WITH_SSL
-    if(fd == sslFd){
-      ret = SSL_read(ssl, buffer + total, N - total);
-    }else{
-      ret = read(fd,buffer + total,N - total);
-    }
-#else /* WITH_SSL */
-    ret = read(fd,buffer + total,N - total);
-#endif /* WITH_SSL */
+      ret	= socket_read( fd, buffer + total, N - total, MSG_WAITALL );
 
     if (ret == 0)
     {
@@ -1188,4 +1140,18 @@
 	DEBUG(5,("unix socket opened: %s\n", path));
 
 	return s;
+}
+
+
+ssize_t socket_read( int fd, void *buf, size_t len, int flags )
+{
+#ifdef WITH_SSL
+    if(fd == sslFd){
+        return SSL_read(ssl, buf, len );
+    }else{
+        return recv( fd, buf, len, flags );
+    }
+#else /* WITH_SSL */
+    return recv( fd, buf, len, flags );
+#endif /* WITH_SSL */
 }




More information about the samba-technical mailing list