summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-08-28 21:46:29 +0000
committerJeremy Allison <jra@samba.org>1998-08-28 21:46:29 +0000
commit38142a1ebbe860778e26eaff68585726061c05e2 (patch)
tree0112dc0186d8088bab727ee8309c36986c9e72d4
parentc077bce5c0f760dc918b0442346502ec96a92c1b (diff)
downloadsamba-38142a1ebbe860778e26eaff68585726061c05e2.tar.gz
samba-38142a1ebbe860778e26eaff68585726061c05e2.tar.bz2
samba-38142a1ebbe860778e26eaff68585726061c05e2.zip
This checking fixes the statcache bug that stopped NetBench from running
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. (This used to be commit 779b924ec1f6c81ff578d22295b20fece698d1fc)
-rw-r--r--source3/client/client.c2
-rw-r--r--source3/client/smbmount.c2
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/lib/system.c70
-rw-r--r--source3/lib/util.c10
-rw-r--r--source3/libsmb/nmblib.c2
-rw-r--r--source3/nmbd/nmbd_packets.c2
-rw-r--r--source3/param/loadparm.c20
-rw-r--r--source3/smbd/filename.c20
-rw-r--r--source3/smbd/server.c2
10 files changed, 91 insertions, 44 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 396028358d..9a4806b7a2 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -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;
diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c
index bd14b121e6..9bc7cba6f6 100644
--- a/source3/client/smbmount.c
+++ b/source3/client/smbmount.c
@@ -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;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 85e00b375b..6594ac6143 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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 );
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 255b1c7b49..d569b80a74 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -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 */
/*******************************************************************
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 4604836f77..414b54bd7c 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -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);
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 9390302ab2..81a9505d6b 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -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));
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index d557414a27..65d98c9a59 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -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. */
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index f6c5769718..44db306d1b 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -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)
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index de4fef5189..9112828092 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -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;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 4c38fb5f4b..1bc6cf273f 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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;