From e8344156bb9d161235d40755635f5bbdd3916ef1 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Jan 1999 02:18:57 +0000 Subject: Converted the code in smbd/dir.c to use bitmaps instead of a static array for directory handles. This tidied up the code a *lot*. Plus it means I've fixed the bug in PR#10058, which was due to an NT app that wanted to simultaneously open >256 directory handles. Jeremy. --- source/include/local.h | 5 + source/include/proto.h | 13 +- source/lib/debug.c | 4 +- source/smbd/dir.c | 424 ++++++++++++++++++++++++++++--------------------- 4 files changed, 255 insertions(+), 191 deletions(-) diff --git a/source/include/local.h b/source/include/local.h index 3261da1cdc3..6aef7f0b8dd 100644 --- a/source/include/local.h +++ b/source/include/local.h @@ -34,6 +34,11 @@ file handle per directory, but large numbers do use more memory */ #define MAX_OPEN_DIRECTORIES 64 +/* max number of directory handles */ +/* As this now uses the bitmap code this can be + quite large. */ +#define MAX_DIRECTORY_HANDLES 2048 + /* define what facility to use for syslog */ #ifndef SYSLOG_FACILITY #define SYSLOG_FACILITY LOG_DAEMON diff --git a/source/include/proto.h b/source/include/proto.h index 1f4f522ac77..72baf1c77ec 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -2412,10 +2412,6 @@ int reply_negprot(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); -/*The following definitions come from smbd/noquotas.c */ - -BOOL disk_quotas(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize); - /*The following definitions come from smbd/nttrans.c */ void fail_next_srvsvc_open(void); @@ -2510,6 +2506,15 @@ void construct_reply_common(char *inbuf,char *outbuf); int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); void smbd_process(void); +/*The following definitions come from smbd/quotas.c */ + +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); +BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); + /*The following definitions come from smbd/reply.c */ int reply_special(char *inbuf,char *outbuf); diff --git a/source/lib/debug.c b/source/lib/debug.c index 02e50aa9213..859fadcafce 100644 --- a/source/lib/debug.c +++ b/source/lib/debug.c @@ -112,7 +112,7 @@ static int debug_count = 0; static int syslog_level = 0; #endif static pstring format_bufr = { '\0' }; -static int format_pos = 0; +static size_t format_pos = 0; /* -------------------------------------------------------------------------- ** @@ -428,7 +428,7 @@ static void bufr_print( void ) */ static void format_debug_text( char *msg ) { - int i; + size_t i; BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() || !(lp_loaded()))); diff --git a/source/smbd/dir.c b/source/smbd/dir.c index dcf1d158b4c..8eea7c76962 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -27,257 +27,321 @@ extern int DEBUGLEVEL; This module implements directory related functions for Samba. */ - - -static uint32 dircounter = 0; - - -#define NUMDIRPTRS 256 - - -static struct dptr_struct { +typedef struct _dptr_struct { + struct _dptr_struct *next, *prev; + int dnum; int pid; connection_struct *conn; - uint32 lastused; void *ptr; - BOOL valid; BOOL finished; BOOL expect_close; char *wcard; /* Field only used for trans2_ searches */ uint16 attr; /* Field only used for trans2_ searches */ char *path; -} -dirptrs[NUMDIRPTRS]; +} dptr_struct; +static struct bitmap *dptr_bmap; +static dptr_struct *dirptrs; static int dptrs_open = 0; /**************************************************************************** -initialise the dir array + Initialise the dir bitmap. ****************************************************************************/ + void init_dptrs(void) { static BOOL dptrs_init=False; - int i; - if (dptrs_init) return; - for (i=0;iptr) { + DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); dptrs_open--; - CloseDir(dirptrs[key].ptr); - dirptrs[key].ptr = NULL; - } + CloseDir(dptr->ptr); + dptr->ptr = NULL; + } } /**************************************************************************** -idle the oldest dptr + Idle the oldest dptr. ****************************************************************************/ + static void dptr_idleoldest(void) { - int i; - uint32 old=dircounter+1; - int oldi= -1; - for (i=0;inext; dptr = dptr->next) + ; + + if(!dptr) { DEBUG(0,("No dptrs available to idle??\n")); + return; + } + + /* + * Now walk back until we find a non-idle ptr. + */ + + for(; dptr; dptr = dptr->prev) { + if (dptr->ptr) + dptr_idle(dptr); + } } /**************************************************************************** -get the dir ptr for a dir index + Get the dptr_struct for a dir index. ****************************************************************************/ -static void *dptr_get(int key,uint32 lastused) + +static dptr_struct *dptr_get(int key) { - struct dptr_struct *dp = &dirptrs[key]; - - if (dp->valid) { - if (lastused) dp->lastused = lastused; - if (!dp->ptr) { - if (dptrs_open >= MAX_OPEN_DIRECTORIES) - dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dp->ptr = OpenDir(dp->conn, dp->path, True))) - dptrs_open++; - } - return(dp->ptr); - } - return(NULL); + dptr_struct *dptr; + + for(dptr = dirptrs; dptr; dptr = dptr->next) { + if(dptr->dnum == key) { + if (!dptr->ptr) { + if (dptrs_open >= MAX_OPEN_DIRECTORIES) + dptr_idleoldest(); + DEBUG(4,("Reopening dptr key %d\n",key)); + if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True))) + dptrs_open++; + } + DLIST_PROMOTE(dirptrs,dptr); + return dptr; + } + } + return(NULL); +} + +/**************************************************************************** + Get the dptr ptr for a dir index. +****************************************************************************/ + +static void *dptr_ptr(int key) +{ + dptr_struct *dptr = dptr_get(key); + + if (dptr) + return(dptr->ptr); + return(NULL); } /**************************************************************************** -get the dir path for a dir index + Get the dir path for a dir index. ****************************************************************************/ + char *dptr_path(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].path); + dptr_struct *dptr = dptr_get(key); + + if (dptr) + return(dptr->path); return(NULL); } /**************************************************************************** -get the dir wcard for a dir index (lanman2 specific) + Get the dir wcard for a dir index (lanman2 specific). ****************************************************************************/ + char *dptr_wcard(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].wcard); + dptr_struct *dptr = dptr_get(key); + + if (dptr) + return(dptr->wcard); return(NULL); } /**************************************************************************** -set the dir wcard for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. + Set the dir wcard for a dir index (lanman2 specific). + Returns 0 on ok, 1 on fail. ****************************************************************************/ + BOOL dptr_set_wcard(int key, char *wcard) { - if (dirptrs[key].valid) { - dirptrs[key].wcard = wcard; + dptr_struct *dptr = dptr_get(key); + + if (dptr) { + dptr->wcard = wcard; return True; } return False; } /**************************************************************************** -set the dir attrib for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. + Set the dir attrib for a dir index (lanman2 specific). + Returns 0 on ok, 1 on fail. ****************************************************************************/ + BOOL dptr_set_attr(int key, uint16 attr) { - if (dirptrs[key].valid) { - dirptrs[key].attr = attr; + dptr_struct *dptr = dptr_get(key); + + if (dptr) { + dptr->attr = attr; return True; } return False; } /**************************************************************************** -get the dir attrib for a dir index (lanman2 specific) + Get the dir attrib for a dir index (lanman2 specific) ****************************************************************************/ + uint16 dptr_attr(int key) { - if (dirptrs[key].valid) - return(dirptrs[key].attr); + dptr_struct *dptr = dptr_get(key); + + if (dptr) + return(dptr->attr); return(0); } /**************************************************************************** -close a dptr + Close a dptr (internal func). ****************************************************************************/ + +static void dptr_close_internal(dptr_struct *dptr) +{ + DEBUG(4,("closing dptr key %d\n",dptr->dnum)); + + DLIST_REMOVE(dirptrs, dptr); + + /* Free the dnum in the bitmap. */ + bitmap_clear(dptr_bmap, dptr->dnum); + + if (dptr->ptr) { + CloseDir(dptr->ptr); + dptrs_open--; + } + + /* Lanman 2 specific code */ + if (dptr->wcard) + free(dptr->wcard); + string_set(&dptr->path,""); + free((char *)dptr); +} + +/**************************************************************************** + Close a dptr given a key. +****************************************************************************/ + void dptr_close(int key) { + dptr_struct *dptr; + /* OS/2 seems to use -1 to indicate "close all directories" */ if (key == -1) { - int i; - for (i=0;inext; + dptr_close_internal(dptr); + } return; } - if (key < 0 || key >= NUMDIRPTRS) { - DEBUG(3,("Invalid key %d given to dptr_close\n",key)); + dptr = dptr_get(key); + + if (!dptr) { + DEBUG(0,("Invalid key %d given to dptr_close\n",key)); return; } - if (dirptrs[key].valid) { - DEBUG(4,("closing dptr key %d\n",key)); - if (dirptrs[key].ptr) { - CloseDir(dirptrs[key].ptr); - dptrs_open--; - } - /* Lanman 2 specific code */ - if (dirptrs[key].wcard) - free(dirptrs[key].wcard); - dirptrs[key].valid = False; - string_set(&dirptrs[key].path,""); - } + dptr_close_internal(dptr); } /**************************************************************************** -close all dptrs for a cnum + Close all dptrs for a cnum. ****************************************************************************/ + void dptr_closecnum(connection_struct *conn) { - int i; - for (i=0;inext; + if (dptr->conn == conn) + dptr_close_internal(dptr); + } } /**************************************************************************** -idle all dptrs for a cnum + Idle all dptrs for a cnum. ****************************************************************************/ + void dptr_idlecnum(connection_struct *conn) { - int i; - for (i=0;inext) { + if (dptr->conn == conn && dptr->ptr) + dptr_idle(dptr); + } } /**************************************************************************** -close a dptr that matches a given path, only if it matches the pid also + Close a dptr that matches a given path, only if it matches the pid also. ****************************************************************************/ + void dptr_closepath(char *path,int pid) { - int i; - for (i=0;inext; + if (pid == dptr->pid && strequal(dptr->path,path)) + dptr_close_internal(dptr); + } } /**************************************************************************** - start a directory listing + Start a directory listing. ****************************************************************************/ + static BOOL start_dir(connection_struct *conn,char *directory) { - DEBUG(5,("start_dir dir=%s\n",directory)); + DEBUG(5,("start_dir dir=%s\n",directory)); - if (!check_name(directory,conn)) - return(False); + if (!check_name(directory,conn)) + return(False); - if (! *directory) - directory = "."; - - conn->dirptr = OpenDir(conn, directory, True); - if (conn->dirptr) { - dptrs_open++; - string_set(&conn->dirpath,directory); - return(True); - } + if (! *directory) + directory = "."; + + conn->dirptr = OpenDir(conn, directory, True); + if (conn->dirptr) { + dptrs_open++; + string_set(&conn->dirpath,directory); + return(True); + } - return(False); + return(False); } /**************************************************************************** -create a new dir ptr + Create a new dir ptr. ****************************************************************************/ + int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid) { - int i; - uint32 old; - int oldi; + dptr_struct *dptr; + int dnum = -1; if (!start_dir(conn,path)) return(-2); /* Code to say use a unix error return code. */ @@ -285,70 +349,50 @@ int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid) if (dptrs_open >= MAX_OPEN_DIRECTORIES) dptr_idleoldest(); - for (i=0;idnum= bitmap_find(dptr_bmap, 0); + if(dptr->dnum == -1) { + DEBUG(0,("dptr_create: Error dirptrs in use??\n")); + free((char *)dptr); + return -1; } - if (dirptrs[i].valid) - dptr_close(i); + bitmap_set(dptr_bmap, dptr->dnum); - dirptrs[i].ptr = conn->dirptr; - string_set(&dirptrs[i].path,path); - dirptrs[i].lastused = dircounter++; - dirptrs[i].finished = False; - dirptrs[i].conn = conn; - dirptrs[i].pid = pid; - dirptrs[i].expect_close = expect_close; - dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */ - dirptrs[i].attr = 0; /* Only used in lanman2 searches */ - dirptrs[i].valid = True; + dptr->ptr = conn->dirptr; + string_set(&dptr->path,path); + dptr->finished = False; + dptr->conn = conn; + dptr->pid = pid; + dptr->expect_close = expect_close; + dptr->wcard = NULL; /* Only used in lanman2 searches */ + dptr->attr = 0; /* Only used in lanman2 searches */ + + DLIST_ADD(dirptrs, dptr); DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", - i,path,expect_close)); + dptr->dnum,path,expect_close)); - return(i); + return(dptr->dnum); } #define DPTR_MASK ((uint32)(((uint32)1)<<31)) /**************************************************************************** -fill the 5 byte server reserved dptr field + Fill the 5 byte server reserved dptr field. ****************************************************************************/ + BOOL dptr_fill(char *buf1,unsigned int key) { unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(key,0); + void *p = dptr_ptr(key); uint32 offset; if (!p) { DEBUG(1,("filling null dirptr %d\n",key)); @@ -364,20 +408,22 @@ BOOL dptr_fill(char *buf1,unsigned int key) /**************************************************************************** -return True is the offset is at zero + Return True is the offset is at zero. ****************************************************************************/ + BOOL dptr_zero(char *buf) { return((IVAL(buf,1)&~DPTR_MASK) == 0); } /**************************************************************************** -fetch the dir ptr and seek it given the 5 byte server field + Fetch the dir ptr and seek it given the 5 byte server field. ****************************************************************************/ + void *dptr_fetch(char *buf,int *num) { unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(key,dircounter++); + void *p = dptr_ptr(key); uint32 offset; if (!p) { DEBUG(3,("fetched null dirptr %d\n",key)); @@ -392,11 +438,12 @@ void *dptr_fetch(char *buf,int *num) } /**************************************************************************** -fetch the dir ptr. + Fetch the dir ptr. ****************************************************************************/ + void *dptr_fetch_lanman2(int dptr_num) { - void *p = dptr_get(dptr_num,dircounter++); + void *p = dptr_ptr(dptr_num); if (!p) { DEBUG(3,("fetched null dirptr %d\n",dptr_num)); @@ -407,8 +454,9 @@ void *dptr_fetch_lanman2(int dptr_num) } /**************************************************************************** -check a filetype for being valid + Check a filetype for being valid. ****************************************************************************/ + BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype) { if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) @@ -417,8 +465,9 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di } /**************************************************************************** - get a directory entry + Get a directory entry. ****************************************************************************/ + BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname, SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) { @@ -512,8 +561,9 @@ typedef struct /******************************************************************* -open a directory + Open a directory. ********************************************************************/ + void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) { Dir *dirp; @@ -560,8 +610,9 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto) /******************************************************************* -close a directory + Close a directory. ********************************************************************/ + void CloseDir(void *p) { Dir *dirp = (Dir *)p; @@ -571,8 +622,9 @@ void CloseDir(void *p) } /******************************************************************* -read from a directory + Read from a directory. ********************************************************************/ + char *ReadDirName(void *p) { char *ret; @@ -589,8 +641,9 @@ char *ReadDirName(void *p) /******************************************************************* -seek a dir + Seek a dir. ********************************************************************/ + BOOL SeekDir(void *p,int pos) { Dir *dirp = (Dir *)p; @@ -608,8 +661,9 @@ BOOL SeekDir(void *p,int pos) } /******************************************************************* -tell a dir position + Tell a dir position. ********************************************************************/ + int TellDir(void *p) { Dir *dirp = (Dir *)p; -- cgit