diff options
author | Andrew Tridgell <tridge@samba.org> | 1998-08-16 04:08:47 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1998-08-16 04:08:47 +0000 |
commit | 739d0b1ddc58bbb792c3eebe8c545602a4fae438 (patch) | |
tree | 3c8c93608f4ce3d870de18cee6673c2efea799da /source3/smbd/files.c | |
parent | a7acf10566af549eb71e7a421397c8073d55e0f6 (diff) | |
download | samba-739d0b1ddc58bbb792c3eebe8c545602a4fae438.tar.gz samba-739d0b1ddc58bbb792c3eebe8c545602a4fae438.tar.xz samba-739d0b1ddc58bbb792c3eebe8c545602a4fae438.zip |
got rid of the Files[] array completely (previously I'd just made it
private to files.c)
It now is a doubly linked list with a bitmap for allocated file
numbers. Similarly for the fd_ptr code. I also changed the default
maximum number of open files to 4096. The static cost is 1 bit per
file.
It all seems to work, and it passes the "does Sue scream" test, but if
you see weird behaviour then please investigate. With the volume of
new code that has gone in there are bound to be one or two bugs
lurking.
note that you must do a "make clean" before building this as many data
structures have changed in size.
(This used to be commit 79755ce97004b787d7e83a8d18fc4c7c003b7231)
Diffstat (limited to 'source3/smbd/files.c')
-rw-r--r-- | source3/smbd/files.c | 353 |
1 files changed, 207 insertions, 146 deletions
diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 04aff67a155..66fbaebeb09 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -23,20 +23,23 @@ extern int DEBUGLEVEL; -#define MAX_OPEN_FILES 100 +/* the only restriction is that this must be less than PIPE_HANDLE_OFFSET */ +#define MAX_FNUMS 4096 -#define MAX_FNUMS (MAX_OPEN_FILES+MAX_OPEN_DIRECTORIES) #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_FNUMS)) -static files_struct Files[MAX_FNUMS]; +static struct bitmap *file_bmap; +static struct bitmap *fd_bmap; + +static files_struct *Files; /* * Indirection for file fd's. Needed as POSIX locking * is based on file/process, not fd/process. */ -static file_fd_struct FileFd[MAX_OPEN_FILES]; -static int max_file_fd_used = 0; +static file_fd_struct *FileFd; +static int files_used, fd_ptr_used; /**************************************************************************** find first available file slot @@ -45,6 +48,7 @@ files_struct *file_new(void ) { int i; static int first_file; + files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -56,59 +60,55 @@ files_struct *file_new(void ) if (first_file == 0) first_file = 1; } - if (first_file >= MAX_FNUMS) + if (first_file >= MAX_FNUMS) { first_file = 1; + } - for (i=first_file;i<MAX_FNUMS;i++) - if (!Files[i].open && !Files[i].reserved) { - memset(&Files[i], 0, sizeof(Files[i])); - first_file = i+1; - Files[i].reserved = True; - Files[i].fnum = i; - return &Files[i]; + i = bitmap_find(file_bmap, first_file); + if (i == -1) { + /* + * Before we give up, go through the open files + * and see if there are any files opened with a + * batch oplock. If so break the oplock and then + * re-use that entry (if it becomes closed). + * This may help as NT/95 clients tend to keep + * files batch oplocked for quite a long time + * after they have finished with them. + */ + for (fsp=Files;fsp;fsp=fsp->next) { + if (attempt_close_oplocked_file(fsp)) { + return file_new(); + } } - /* returning a file handle of 0 is a bad idea - so we start at 1 */ - for (i=1;i<first_file;i++) - if (!Files[i].open && !Files[i].reserved) { - memset(&Files[i], 0, sizeof(Files[i])); - first_file = i+1; - Files[i].reserved = True; - Files[i].fnum = i; - return &Files[i]; - } + DEBUG(0,("ERROR! Out of file structures\n")); + return NULL; + } - /* - * Before we give up, go through the open files - * and see if there are any files opened with a - * batch oplock. If so break the oplock and then - * re-use that entry (if it becomes closed). - * This may help as NT/95 clients tend to keep - * files batch oplocked for quite a long time - * after they have finished with them. - */ - for (i=first_file;i<MAX_FNUMS;i++) { - if(attempt_close_oplocked_file( &Files[i])) { - memset(&Files[i], 0, sizeof(Files[i])); - first_file = i+1; - Files[i].reserved = True; - Files[i].fnum = i; - return &Files[i]; - } - } - - for (i=1;i<MAX_FNUMS;i++) { - if(attempt_close_oplocked_file( &Files[i])) { - memset(&Files[i], 0, sizeof(Files[i])); - first_file = i+1; - Files[i].reserved = True; - Files[i].fnum = i; - return &Files[i]; - } - } - - DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n")); - return NULL; + fsp = (files_struct *)malloc(sizeof(*fsp)); + if (!fsp) return NULL; + + memset(fsp, 0, sizeof(*fsp)); + first_file = i+1; + fsp->fnum = i; + string_init(&fsp->fsp_name,""); + + bitmap_set(file_bmap, i); + files_used++; + + /* hook into the front of the list */ + if (!Files) { + Files = fsp; + } else { + Files->prev = fsp; + fsp->next = Files; + Files = fsp; + } + + DEBUG(5,("allocated file structure %d (%d used)\n", + i, files_used)); + + return fsp; } @@ -119,60 +119,74 @@ and inode - increments the ref_count of the returned file_fd_struct *. ****************************************************************************/ file_fd_struct *fd_get_already_open(struct stat *sbuf) { - int i; - file_fd_struct *fd_ptr; - - if(sbuf == 0) - return 0; - - for(i = 0; i <= max_file_fd_used; i++) { - fd_ptr = &FileFd[i]; - if((fd_ptr->ref_count > 0) && - (((uint32)sbuf->st_dev) == fd_ptr->dev) && - (((uint32)sbuf->st_ino) == fd_ptr->inode)) { - fd_ptr->ref_count++; - DEBUG(3, - ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", - i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); - return fd_ptr; - } - } - return 0; + file_fd_struct *fd_ptr; + + if(!sbuf) return NULL; + + for (fd_ptr=FileFd;fd_ptr;fd_ptr=fd_ptr->next) { + if ((fd_ptr->ref_count > 0) && + (((uint32)sbuf->st_dev) == fd_ptr->dev) && + (((uint32)sbuf->st_ino) == fd_ptr->inode)) { + fd_ptr->ref_count++; + DEBUG(3,("Re-used file_fd_struct dev = %x, inode = %x, ref_count = %d\n", + fd_ptr->dev, fd_ptr->inode, + fd_ptr->ref_count)); + return fd_ptr; + } + } + + return NULL; } + + /**************************************************************************** fd support routines - attempt to find a empty slot in the FileFd array. Increments the ref_count of the returned entry. ****************************************************************************/ file_fd_struct *fd_get_new(void) { - extern struct current_user current_user; - int i; - file_fd_struct *fd_ptr; - - for(i = 0; i < MAX_OPEN_FILES; i++) { - fd_ptr = &FileFd[i]; - if(fd_ptr->ref_count == 0) { - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->uid_cache_count = 0; - fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); - fd_ptr->ref_count++; - /* Increment max used counter if neccessary, cuts down - on search time when re-using */ - if(i > max_file_fd_used) - max_file_fd_used = i; - DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", - i, fd_ptr->dev, fd_ptr->inode)); - return fd_ptr; - } - } - DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\n")); - return 0; + extern struct current_user current_user; + int i; + file_fd_struct *fd_ptr; + + i = bitmap_find(fd_bmap, 1); + if (i == -1) { + DEBUG(0,("ERROR! Out of file_fd structures\n")); + return NULL; + } + + fd_ptr = (file_fd_struct *)malloc(sizeof(*fd_ptr)); + if (!fd_ptr) return NULL; + + memset(fd_ptr, 0, sizeof(*fd_ptr)); + + fd_ptr->fdnum = i; + fd_ptr->dev = (uint32)-1; + fd_ptr->inode = (uint32)-1; + fd_ptr->fd = -1; + fd_ptr->fd_readonly = -1; + fd_ptr->fd_writeonly = -1; + fd_ptr->real_open_flags = -1; + fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid); + fd_ptr->ref_count++; + + bitmap_set(fd_bmap, i); + fd_ptr_used++; + + /* hook into the front of the list */ + if (!FileFd) { + FileFd = fd_ptr; + } else { + FileFd->prev = fd_ptr; + fd_ptr->next = FileFd; + FileFd = fd_ptr; + } + + DEBUG(5,("allocated fd_ptr structure %d (%d used)\n", + i, fd_ptr_used)); + + return fd_ptr; } @@ -181,14 +195,16 @@ close all open files for a connection ****************************************************************************/ void file_close_conn(connection_struct *conn) { - int i; - for (i=0;i<MAX_FNUMS;i++) - if (Files[i].conn == conn && Files[i].open) { - if(Files[i].is_directory) - close_directory(&Files[i]); - else - close_file(&Files[i],False); - } + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->conn == conn && fsp->open) { + if (fsp->is_directory) + close_directory(fsp); + else + close_file(fsp,False); + } + } } /**************************************************************************** @@ -196,10 +212,14 @@ initialise file structures ****************************************************************************/ void file_init(void) { - int i; + file_bmap = bitmap_allocate(MAX_FNUMS); + fd_bmap = bitmap_allocate(MAX_FNUMS); + + if (!file_bmap || !fd_bmap) { + exit_server("out of memory in file_init"); + } -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_NOFILE +#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) { struct rlimit rlp; getrlimit(RLIMIT_NOFILE, &rlp); @@ -215,34 +235,23 @@ void file_init(void) (int)rlp.rlim_cur)); } #endif -#endif - - - - for (i=0;i<MAX_FNUMS;i++) { - Files[i].open = False; - string_init(&Files[i].fsp_name,""); - } - - for (i=0;i<MAX_OPEN_FILES;i++) { - file_fd_struct *fd_ptr = &FileFd[i]; - fd_ptr->ref_count = 0; - fd_ptr->dev = (int32)-1; - fd_ptr->inode = (int32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - } } + /**************************************************************************** find a fsp given a fnum ****************************************************************************/ files_struct *file_fsp(int fnum) { + files_struct *fsp; + if (!VALID_FNUM(fnum)) return NULL; - return &Files[fnum]; + + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->fnum == fnum) return fsp; + } + + return NULL; } @@ -251,9 +260,9 @@ close files open by a specified vuid ****************************************************************************/ void file_close_user(int vuid) { - int i; - for (i=0;i<MAX_FNUMS;i++) { - files_struct *fsp = &Files[i]; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { if ((fsp->vuid == vuid) && fsp->open) { if(!fsp->is_directory) close_file(fsp,False); @@ -269,9 +278,9 @@ find a fsp given a device, inode and timevalue ****************************************************************************/ files_struct *file_find_dit(int dev, int inode, struct timeval *tval) { - int i; - for (i=0;i<MAX_FNUMS;i++) { - files_struct *fsp = &Files[i]; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && fsp->fd_ptr->dev == dev && fsp->fd_ptr->inode == inode && @@ -279,22 +288,21 @@ files_struct *file_find_dit(int dev, int inode, struct timeval *tval) fsp->open_time.tv_usec == tval->tv_usec) { return fsp; } - } + } + return NULL; } + /**************************************************************************** find a fsp that is open for printing ****************************************************************************/ files_struct *file_find_print(void) { - int i; + files_struct *fsp; - for (i=0;i<MAX_FNUMS;i++) { - files_struct *fsp = &Files[i]; - if (fsp->open && fsp->print_file) { - return fsp; - } + for (fsp=Files;fsp;fsp=fsp->next) { + if (fsp->open && fsp->print_file) return fsp; } return NULL; } @@ -305,9 +313,9 @@ sync open files on a connection ****************************************************************************/ void file_sync_all(connection_struct *conn) { - int i; - for (i=0;i<MAX_FNUMS;i++) { - files_struct *fsp = &Files[i]; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next) { if (fsp->open && conn == fsp->conn) { sync_file(conn,fsp); } @@ -315,7 +323,60 @@ void file_sync_all(connection_struct *conn) } +/**************************************************************************** +free up a fd_ptr +****************************************************************************/ +static void fd_ptr_free(file_fd_struct *fd_ptr) +{ + if (fd_ptr == FileFd) { + FileFd = fd_ptr->next; + if (FileFd) FileFd->prev = NULL; + } else { + fd_ptr->prev->next = fd_ptr->next; + if (fd_ptr->next) fd_ptr->next->prev = fd_ptr->prev; + } + + bitmap_clear(fd_bmap, fd_ptr->fdnum); + fd_ptr_used--; + + DEBUG(5,("freed fd_ptr structure %d (%d used)\n", + fd_ptr->fdnum, fd_ptr_used)); + + /* paranoia */ + memset(fd_ptr, 0, sizeof(*fd_ptr)); + + free(fd_ptr); +} + + +/**************************************************************************** +free up a fsp +****************************************************************************/ void file_free(files_struct *fsp) { + if (fsp == Files) { + Files = fsp->next; + if (Files) Files->prev = NULL; + } else { + fsp->prev->next = fsp->next; + if (fsp->next) fsp->next->prev = fsp->prev; + } + + string_free(&fsp->fsp_name); + + if (fsp->fd_ptr && fsp->fd_ptr->ref_count == 0) { + fd_ptr_free(fsp->fd_ptr); + } + + bitmap_clear(file_bmap, fsp->fnum); + files_used--; + + DEBUG(5,("freed files structure %d (%d used)\n", + fsp->fnum, files_used)); + + /* this is paranoia, just in case someone tries to reuse the + information */ memset(fsp, 0, sizeof(*fsp)); + + free(fsp); } |