This checking fixes the statcache bug that stopped NetBench from running
authorJeremy Allison <jra@samba.org>
Fri, 28 Aug 1998 21:46:29 +0000 (21:46 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 28 Aug 1998 21:46:29 +0000 (21:46 +0000)
correctly. Added new parameter "stat cache size" - set to 50 by default.

I now declare the statcache code officially "open" for business :-).
It gets a hit rate of 97% with a NetBench run and seems to make
using a case insensitive run as efficient as a case sensitive run.

Also tidied up our sys_select usage - added a maxfd parameter and
also added an implementation of select in terms of poll(), for systems
where poll() is much faster. This is disabled by default.

Jeremy.

source/client/client.c
source/client/smbmount.c
source/include/proto.h
source/lib/system.c
source/lib/util.c
source/libsmb/nmblib.c
source/nmbd/nmbd_packets.c
source/param/loadparm.c
source/smbd/filename.c
source/smbd/server.c

index 396028358d549ef314bc9c7d1429be11c44bd137..9a4806b7a2f6fd5d9c4e406ea264853cb17e89e8 100644 (file)
@@ -3333,7 +3333,7 @@ static void wait_keyboard(char *buffer)
 
       timeout.tv_sec = 20;
       timeout.tv_usec = 0;
-      selrtn = sys_select(&fds,&timeout);
+      selrtn = sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
       
       if (FD_ISSET(fileno(stdin),&fds))
        return;
index bd14b121e631e2587d6a78aff01f71783f6f2d19..9bc7cba6f652a2b4cb022b21b8390cfc9a57f814 100644 (file)
@@ -463,7 +463,7 @@ static void wait_keyboard(char *buffer)
 
       timeout.tv_sec = 20;
       timeout.tv_usec = 0;
-      selrtn = sys_select(&fds,&timeout);
+      selrtn = sys_select(MAX(Client,fileno(stdin))+1,&fds,&timeout);
       
       if (FD_ISSET(fileno(stdin),&fds))
        return;
index 85e00b375bc2e5eac69999180f57ebc567451bbe..6594ac6143a0201c99ac47ce9fe1b52856ea2382 100644 (file)
@@ -162,8 +162,8 @@ int smbrun(char *cmd,char *outfile,BOOL shared);
 
 /*The following definitions come from  lib/system.c  */
 
-int sys_select(fd_set *fds,struct timeval *tval);
-int sys_select(fd_set *fds,struct timeval *tval);
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval);
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval);
 int sys_unlink(char *fname);
 int sys_open(char *fname,int flags,int mode);
 DIR *sys_opendir(char *dname);
@@ -992,6 +992,7 @@ int lp_lm_announce(void);
 int lp_lm_interval(void);
 int lp_machine_password_timeout(void);
 int lp_change_notify_timeout(void);
+int lp_stat_cache_size(void);
 int lp_ldap_port(void);
 char *lp_preexec(int );
 char *lp_postexec(int );
index 255b1c7b49b21bb76946b6ef0e5fe656f449cff1..d569b80a748578b071349ec0a9174714bca663cf 100644 (file)
@@ -60,7 +60,7 @@ static int pollfd(int fd)
   return(r);
 }
 
-int sys_select(fd_set *fds,struct timeval *tval)
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
 {
   fd_set fds2;
   int counter=0;
@@ -69,41 +69,75 @@ int sys_select(fd_set *fds,struct timeval *tval)
   FD_ZERO(&fds2);
 
   while (1) 
-    {
-      int i;
-      for (i=0;i<255;i++) {
-       if (FD_ISSET(i,fds) && pollfd(i)>0) {
-         found++;
-         FD_SET(i,&fds2);
-       }
+  {
+    int i;
+    for (i=0;i<maxfd;i++) {
+      if (FD_ISSET(i,fds) && pollfd(i)>0) {
+        found++;
+        FD_SET(i,&fds2);
       }
+    }
 
-      if (found) {
-       memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
-       return(found);
-      }
+    if (found) {
+      memcpy((void *)fds,(void *)&fds2,sizeof(fds2));
+      return(found);
+    }
       
-      if (tval && tval->tv_sec < counter) return(0);
+    if (tval && tval->tv_sec < counter) return(0);
       sleep(1);
       counter++;
-    }
+  }
 }
 
-#else
-int sys_select(fd_set *fds,struct timeval *tval)
+#else /* !NO_SELECT */
+int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
 {
+#ifdef USE_POLL
+  struct pollfd pfd[256];
+  int i;
+  int maxpoll;
+  int timeout;
+  int pollrtn;
+
+  maxpoll = 0;
+  for( i = 0; i < maxfd; i++) {
+    if(FD_ISSET(i,fds)) {
+      struct pollfd *pfdp = &pfd[maxpoll++];
+      pfdp->fd = i;
+      pfdp->events = POLLIN;
+      pfdp->revents = 0;
+    }
+  }
+
+  timeout = (tval != NULL) ? (tval->tv_sec * 1000) + (tval->tv_usec/1000) :
+                -1;
+  errno = 0;
+  do {
+    pollrtn = poll( &pfd[0], maxpoll, timeout);
+  } while (pollrtn<0 && errno == EINTR);
+
+  FD_ZERO(fds);
+
+  for( i = 0; i < maxpoll; i++)
+    if( pfd[i].revents & POLLIN )
+      FD_SET(pfd[i].fd,fds);
+
+  return pollrtn;
+#else /* USE_POLL */
+
   struct timeval t2;
   int selrtn;
 
   do {
     if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
     errno = 0;
-    selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
+    selrtn = select(maxfd,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
   } while (selrtn<0 && errno == EINTR);
 
   return(selrtn);
 }
-#endif
+#endif /* USE_POLL */
+#endif /* NO_SELECT */
 
 
 /*******************************************************************
index 4604836f77d379fb2ca328c4c7744fc65b1d4567..414b54bd7c03f46182cdac6d4dd88bdf2ba8d0ba 100644 (file)
@@ -1883,7 +1883,7 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out)
       FD_ZERO(&fds);
       FD_SET(fd,&fds);
       
-      selrtn = sys_select(&fds,&timeout);
+      selrtn = sys_select(fd+1,&fds,&timeout);
 
       /* Check if error */
       if(selrtn == -1) {
@@ -1943,7 +1943,7 @@ int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
   timeout.tv_sec = maxtime / 1000;
   timeout.tv_usec = (maxtime % 1000) * 1000;
 
-  selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
+  selrtn = sys_select(fd+1,&fds,maxtime>0?&timeout:NULL);
 
   if (!FD_ISSET(fd,&fds))
     return 0;
@@ -2269,7 +2269,7 @@ BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout)
     to.tv_sec = timeout / 1000;
     to.tv_usec = (timeout % 1000) * 1000;
 
-    selrtn = sys_select(&fds,&to);
+    selrtn = sys_select(fd+1,&fds,&to);
 
     /* Check if error */
     if(selrtn == -1) 
@@ -2437,7 +2437,7 @@ BOOL receive_message_or_smb(int smbfd, int oplock_fd,
   to.tv_sec = timeout / 1000;
   to.tv_usec = (timeout % 1000) * 1000;
 
-  selrtn = sys_select(&fds,timeout>0?&to:NULL);
+  selrtn = sys_select(MAX(smbfd,oplock_fd)+1,&fds,timeout>0?&to:NULL);
 
   /* Check if error */
   if(selrtn == -1) {
@@ -2601,7 +2601,7 @@ void msleep(int t)
  
     FD_ZERO(&fds);
     errno = 0;
-    sys_select(&fds,&tval);
+    sys_select(0,&fds,&tval);
 
     GetTimeOfDay(&t2);
     tdiff = TvalDiff(&t1,&t2);
index 9390302ab236432afe2aa26c627a90e15fdad6d5..81a9505d6b2c56795fc1008fc555e50af12a52bc 100644 (file)
@@ -899,7 +899,7 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
   timeout.tv_sec = t/1000;
   timeout.tv_usec = 1000*(t%1000);
 
-  sys_select(&fds,&timeout);
+  sys_select(fd+1,&fds,&timeout);
 
   if (FD_ISSET(fd,&fds)) 
     return(read_packet(fd,type));
index d557414a272bb89a2cc251fa869ca27e1424cfd6..65d98c9a5964ff7a6ed06115ff045223d7f0791b 100644 (file)
@@ -1773,7 +1773,7 @@ BOOL listen_for_packets(BOOL run_election)
   BlockSignals(False, SIGUSR2);
 #endif /* SIGUSR2 */
 
-  selrtn = sys_select(&fds,&timeout);
+  selrtn = sys_select(256,&fds,&timeout);
 
   /* We can only take signals when we are in the select - block them again here. */
 
index f6c5769718719895adfc49b61dedf6565a7e7741..44db306d1b2d7c4a8e03db232ccaa6fb6a93c23a 100644 (file)
@@ -178,6 +178,7 @@ typedef struct
   int announce_as;   /* This is initialised in init_globals */
   int machine_password_timeout;
   int change_notify_timeout;
+  int stat_cache_size;
 #ifdef WITH_LDAP
   int ldap_port;
 #endif /* WITH_LDAP */
@@ -579,19 +580,20 @@ static struct parm_struct parm_table[] =
 
   {"Tuning Options", P_SEP, P_SEPARATOR},
   {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL,   NULL,  0},
-  {"max disk size",    P_INTEGER, P_GLOBAL, &Globals.maxdisksize,       NULL,   NULL,  0},
-  {"lpq cache time",   P_INTEGER, P_GLOBAL, &Globals.lpqcachetime,      NULL,   NULL,  0},
+  {"deadtime",         P_INTEGER, P_GLOBAL, &Globals.deadtime,          NULL,   NULL,  0},
   {"getwd cache",      P_BOOL,    P_GLOBAL, &use_getwd_cache,           NULL,   NULL,  0},
-  {"read prediction",  P_BOOL,    P_GLOBAL, &Globals.bReadPrediction,   NULL,   NULL,  0},
-  {"socket options",   P_GSTRING, P_GLOBAL, user_socket_options,        NULL,   NULL,  0},
   {"keepalive",        P_INTEGER, P_GLOBAL, &keepalive,                 NULL,   NULL,  0},
-  {"deadtime",         P_INTEGER, P_GLOBAL, &Globals.deadtime,          NULL,   NULL,  0},
-  {"read size",        P_INTEGER, P_GLOBAL, &Globals.ReadSize,          NULL,   NULL,  0},
-  {"shared mem size",  P_INTEGER, P_GLOBAL, &Globals.shmem_size,        NULL,   NULL,  0},
+  {"lpq cache time",   P_INTEGER, P_GLOBAL, &Globals.lpqcachetime,      NULL,   NULL,  0},
   {"max connections",  P_INTEGER, P_LOCAL,  &sDefault.iMaxConnections,  NULL,   NULL,  0},
+  {"max disk size",    P_INTEGER, P_GLOBAL, &Globals.maxdisksize,       NULL,   NULL,  0},
   {"min print space",  P_INTEGER, P_LOCAL,  &sDefault.iMinPrintSpace,   NULL,   NULL,  0},
-  {"sync always",      P_BOOL,    P_LOCAL,  &sDefault.bSyncAlways,      NULL,   NULL,  0},
+  {"read prediction",  P_BOOL,    P_GLOBAL, &Globals.bReadPrediction,   NULL,   NULL,  0},
+  {"read size",        P_INTEGER, P_GLOBAL, &Globals.ReadSize,          NULL,   NULL,  0},
+  {"shared mem size",  P_INTEGER, P_GLOBAL, &Globals.shmem_size,        NULL,   NULL,  0},
+  {"socket options",   P_GSTRING, P_GLOBAL, user_socket_options,        NULL,   NULL,  0},
+  {"stat cache size",  P_INTEGER, P_GLOBAL, &Globals.stat_cache_size,   NULL,   NULL,  0},
   {"strict sync",      P_BOOL,    P_LOCAL,  &sDefault.bStrictSync,      NULL,   NULL,  0},
+  {"sync always",      P_BOOL,    P_LOCAL,  &sDefault.bSyncAlways,      NULL,   NULL,  0},
 
   {"Printing Options", P_SEP, P_SEPARATOR},
   {"load printers",    P_BOOL,    P_GLOBAL, &Globals.bLoadPrinters,     NULL,   NULL,  0},
@@ -827,6 +829,7 @@ static void init_globals(void)
   Globals.lm_announce = 2;   /* = Auto: send only if LM clients found */
   Globals.lm_interval = 60;
   Globals.shmem_size = SHMEM_SIZE;
+  Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */
   Globals.announce_as = ANNOUNCE_AS_NT;
   Globals.bUnixRealname = False;
 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
@@ -1163,6 +1166,7 @@ FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
 FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
 FN_GLOBAL_INTEGER(lp_change_notify_timeout,&Globals.change_notify_timeout)
+FN_GLOBAL_INTEGER(lp_stat_cache_size,&Globals.stat_cache_size)
 
 #ifdef WITH_LDAP
 FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)
index de4fef5189b8cb5a4e329ab4e2db6b4ad17f54e1..9112828092865274d603103223789c2fd0839efe 100644 (file)
@@ -115,7 +115,8 @@ typedef struct {
 static ubi_dlList stat_cache = { NULL, (ubi_dlNodePtr)&stat_cache, 0};
 
 /****************************************************************************
- Compare two names in the stat cache.
+ Compare two names in the stat cache - to check if we already have such an
+ entry.
 *****************************************************************************/
 
 static BOOL stat_name_equal( char *s1, char *s2)
@@ -124,13 +125,20 @@ static BOOL stat_name_equal( char *s1, char *s2)
 }
 
 /****************************************************************************
- Compare two names in the stat cache.
+ Compare a pathname to a name in the stat cache - of a given length.
+ Note - this code always checks that the next character in the pathname
+ is either a '/' character, or a '\0' character - to ensure we only
+ match *full* pathname components.
 *****************************************************************************/
 
-static BOOL stat_name_equal_len( char *s1, char *s2, int len)
+static BOOL stat_name_equal_len( char *stat_name, char *orig_name, int len)
 {
-  return (case_sensitive ? (strncmp( s1, s2, len) == 0) : 
-                           (StrnCaseCmp(s1, s2, len) == 0));
+  BOOL matched = (case_sensitive ? (strncmp( stat_name, orig_name, len) == 0) :
+                           (StrnCaseCmp(stat_name, orig_name, len) == 0));
+  if(orig_name[len] != '/' && orig_name[len] != '\0')
+    return False;
+
+  return matched;
 }
 
 /****************************************************************************
@@ -211,7 +219,7 @@ static void stat_cache_add( char *full_orig_name, char *orig_translated_path)
 
   DEBUG(10,("stat_cache_add: Added entry %s -> %s\n", scp->orig_name, scp->translated_name ));
 
-  if(ubi_dlCount(&stat_cache) > MAX_STAT_CACHE_SIZE) {
+  if(ubi_dlCount(&stat_cache) > lp_stat_cache_size()) {
     scp = (stat_cache_entry *)ubi_dlRemTail( &stat_cache );
     free((char *)scp);
     return;
index 4c38fb5f4b7d95a80fecf2932c97bac179e5a345..1bc6cf273f03aaa869c97f121fe4322dc1913cd5 100644 (file)
@@ -208,7 +208,7 @@ max can be %d\n",
                memcpy((char *)&lfds, (char *)&listen_set, 
                       sizeof(listen_set));
                
-               num = sys_select(&lfds,NULL);
+               num = sys_select(256,&lfds,NULL);
                
                if (num == -1 && errno == EINTR)
                        continue;