From 700f72453ed8dfd356a5591b9447127b5066ac4b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 30 Apr 2000 11:04:28 +0000 Subject: - removed all our old wildcard matching code and replaced it with a call to ms_fnmatch(). This also removes all the Win9X semantics stuff and a bunch of other associated cruft. - moved the stat cache code into statcache.c - fixed the uint16 alignment requirements of ascii_to_unistr() and unistr_to_ascii() - trans2 SMB_FIND_FILE_BOTH_DIRECTORY_INFO returns the short name as unicode always (at least thats what NT4 does) - fixed some errors in the in-memory tdb code. Still ugly, but doesn't crash as much (This used to be commit 03e9cea004bbba72161a5323cf3b4556c94aed8e) --- source3/smbd/statcache.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 source3/smbd/statcache.c (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c new file mode 100644 index 0000000000..ae5dbb1ef7 --- /dev/null +++ b/source3/smbd/statcache.c @@ -0,0 +1,243 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + stat cache code + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 1999-200 + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern BOOL case_sensitive; + + +/**************************************************************************** + Stat cache code used in unix_convert. +*****************************************************************************/ + +static int global_stat_cache_lookups; +static int global_stat_cache_misses; +static int global_stat_cache_hits; + +/**************************************************************************** + Stat cache statistics code. +*****************************************************************************/ + +void print_stat_cache_statistics(void) +{ + double eff; + + if(global_stat_cache_lookups == 0) + return; + + eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; + + DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ +stat cache was %f%% effective.\n", global_stat_cache_lookups, + global_stat_cache_hits, global_stat_cache_misses, eff )); +} + +typedef struct { + int name_len; + char names[2]; /* This is extended via malloc... */ +} stat_cache_entry; + +#define INIT_STAT_CACHE_SIZE 512 +static hash_table stat_cache; + +/**************************************************************************** + Add an entry into the stat cache. +*****************************************************************************/ + +void stat_cache_add( char *full_orig_name, char *orig_translated_path) +{ + stat_cache_entry *scp; + stat_cache_entry *found_scp; + pstring orig_name; + pstring translated_path; + int namelen; + hash_element *hash_elem; + + if (!lp_stat_cache()) return; + + namelen = strlen(orig_translated_path); + + /* + * Don't cache trivial valid directory entries. + */ + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) + return; + + /* + * If we are in case insentive mode, we need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + pstrcpy(translated_path, orig_translated_path); + if(translated_path[namelen-1] == '/') { + translated_path[namelen-1] = '\0'; + namelen--; + } + + /* + * We will only replace namelen characters + * of full_orig_name. + * StrnCpy always null terminates. + */ + + StrnCpy(orig_name, full_orig_name, namelen); + if(!case_sensitive) + strupper( orig_name ); + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { + return; + } else { + hash_remove(&stat_cache, hash_elem); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy((scp->names+namelen+1), translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); + } + return; + } else { + + /* + * New entry. + */ + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + return; + } + pstrcpy(scp->names, orig_name); + pstrcpy(scp->names+namelen+1, translated_path); + scp->name_len = namelen; + hash_insert(&stat_cache, (char *)scp, orig_name); + } + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); +} + +/**************************************************************************** + Look through the stat cache for an entry - promote it to the top if found. + Return True if we translated (and did a scuccessful stat on) the entire name. +*****************************************************************************/ + +BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, + char **start, SMB_STRUCT_STAT *pst) +{ + stat_cache_entry *scp; + char *trans_name; + pstring chk_name; + int namelen; + hash_element *hash_elem; + char *sp; + + if (!lp_stat_cache()) + return False; + + namelen = strlen(name); + + *start = name; + global_stat_cache_lookups++; + + /* + * Don't lookup trivial valid directory entries. + */ + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + global_stat_cache_misses++; + return False; + } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + global_stat_cache_misses++; + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + global_stat_cache_hits++; + trans_name = scp->names+scp->name_len+1; + if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, trans_name, scp->name_len); + *start = &name[scp->name_len]; + if(**start == '/') + ++*start; + StrnCpy( dirpath, trans_name, name - (*start)); + return (namelen == scp->name_len); + } + } +} + +/*************************************************************************** ** + * Initializes or clears the stat cache. + * + * Input: none. + * Output: none. + * + * ************************************************************************** ** + */ +BOOL reset_stat_cache( void ) +{ + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); +} /* reset_stat_cache */ -- cgit From c39e2e6f9a9fb3ac2e21ef31eaad6d280cfc3d9e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 May 2000 07:10:54 +0000 Subject: fixed a memory leak (calling hash_table_init twice) (This used to be commit 610fcef4d33db2b62e6298bdb68546a2411d03b1) --- source3/smbd/statcache.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index ae5dbb1ef7..e0ceddff1d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -239,5 +239,11 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + static BOOL initialised; + if (!initialised) { + initialised = True; + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + } + hash_clear(&stat_cache); + return True; } /* reset_stat_cache */ -- cgit From 6ed606cab4e9fc4c954576ffe1d0d781d3e21929 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 May 2000 06:28:38 +0000 Subject: if the stat cache is off then don't initialise it (This used to be commit cd5dcd9e659a7255f03eb496c0202986375e73a6) --- source3/smbd/statcache.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index e0ceddff1d..7b8701337f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -240,6 +240,8 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, BOOL reset_stat_cache( void ) { static BOOL initialised; + if (!lp_stat_cache()) return True; + if (!initialised) { initialised = True; return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); -- cgit From 4248374c84a3564de3c2cc728612b73ba72e2443 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 4 Oct 2000 22:37:33 +0000 Subject: Made re-init of stat cache explicit rather than being hidden. Jeremy. (This used to be commit b0c40236bb4381fec0e812c20e5f8c09ebf005f9) --- source3/smbd/statcache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7b8701337f..7b2916bb9a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -247,5 +247,6 @@ BOOL reset_stat_cache( void ) return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); } hash_clear(&stat_cache); - return True; + return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + } /* reset_stat_cache */ -- cgit From 636f146abf0a75cd3b21a57b50627ee149a635ab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 03:21:49 +0000 Subject: Restructuring of vfs layer to include a "this" pointer - can be an fsp or a conn struct depending on the call. We need this to have a clean NT ACL call interface. This will break any existing VFS libraries (that's why this is pre-release code). Andrew gets credit for this one :-) :-). In addition - added Herb's WITH_PROFILE changes - Herb - please examine the changes I've made to the smbd/reply.c code you added. The original code was very ugly and I have replaced it with a START_PROFILE(x)/END_PROFILE(x) pair using the preprocessor. Please check this compiles ok with the --with-profile switch. Jeremy. (This used to be commit b07611f8159b0b3f42e7e02611be9f4d56de96f5) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7b2916bb9a..b66c5e2fe9 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -214,7 +214,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, scp = (stat_cache_entry *)(hash_elem->value); global_stat_cache_hits++; trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(dos_to_unix(trans_name,False), pst) != 0) { + if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; -- cgit From ba00796e6dd13b87b7988a98e532676d9eab702c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Oct 2000 18:13:52 +0000 Subject: Herb's warning fixes. Also the POSIX locking fix. We now use our own vfs layer to do get/set acl calls (hurrah!). Jeremy. (This used to be commit dfe77c7046cbd65ee52aea7439f21503c1eac41d) --- source3/smbd/statcache.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b66c5e2fe9..8d756a1d46 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -30,28 +30,6 @@ extern BOOL case_sensitive; Stat cache code used in unix_convert. *****************************************************************************/ -static int global_stat_cache_lookups; -static int global_stat_cache_misses; -static int global_stat_cache_hits; - -/**************************************************************************** - Stat cache statistics code. -*****************************************************************************/ - -void print_stat_cache_statistics(void) -{ - double eff; - - if(global_stat_cache_lookups == 0) - return; - - eff = (100.0* (double)global_stat_cache_hits)/(double)global_stat_cache_lookups; - - DEBUG(0,("stat cache stats: lookups = %d, hits = %d, misses = %d, \ -stat cache was %f%% effective.\n", global_stat_cache_lookups, - global_stat_cache_hits, global_stat_cache_misses, eff )); -} - typedef struct { int name_len; char names[2]; /* This is extended via malloc... */ @@ -175,13 +153,14 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, namelen = strlen(name); *start = name; - global_stat_cache_lookups++; + + DO_PROFILE_INC(statcache_lookups); /* * Don't lookup trivial valid directory entries. */ if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } @@ -202,17 +181,17 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, /* * We reached the end of the name - no match. */ - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { - global_stat_cache_misses++; + DO_PROFILE_INC(statcache_misses); return False; } } else { scp = (stat_cache_entry *)(hash_elem->value); - global_stat_cache_hits++; + DO_PROFILE_INC(statcache_hits); trans_name = scp->names+scp->name_len+1; if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ -- cgit From abf055046fe70842badc2a1904f2cd6966bafbf4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Oct 2000 02:58:24 +0000 Subject: Ok - this is a big patch - and it may break smbd a bit (although I hope not). If you encounter strange file-serving behavior after this patch then back it out. I analysed our stat() usage and realised we were doing approx. 3 stat calls per open, and 2 per getattr/setattr. This patch should fix all that. It causes the stat struct returned from unix_convert() (which now *must* be passed a valid SMB_STRUCT_STAT pointer) to be passed through into the open code. This should prevent the multiple stats that were being done so as not to violate layer encapsulation in the API's. Herb - if you could run a NetBench test with this code and do a padc/par syscall test and also run with the current 2.2.0 code and test the padc/par syscalls I'd appreciate it - you should find the number of stat calls reduced - not sure by how much. The patch depends on unix_convert() actually finding the file and returning a stat struct, or returning a zero'd out stat struct if the file didn't exist. I believe we can guarentee this to be the case - I just wasn't confident enough to make this an assertion before. Ok ok - I did write this whilst at the Miami conference..... sometimes you get a little free time at these things :-). Jeremy. (This used to be commit 66a5c05ec46b641224fbe01b30bd7e83571a2a1b) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8d756a1d46..8200c277b3 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -193,7 +193,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); trans_name = scp->names+scp->name_len+1; - if(conn->vfs_ops.stat(conn,dos_to_unix(trans_name,False), pst) != 0) { + if(vfs_stat(conn,trans_name, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; -- cgit From 2bd3a436fd6ed218bced476b502d24f317511fb2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Nov 2000 00:30:15 +0000 Subject: Fix for updating of print queues changed from a local box. Essentially, this makes sure that the change messages sent to ourselves are handled synchronously w.r.t. other smb packets incoming. Jeremy. (This used to be commit 78a13074455618308d048d1c69f62e660988eb90) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8200c277b3..4c885f34f1 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -218,7 +218,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised; + static BOOL initialised = False; if (!lp_stat_cache()) return True; if (!initialised) { -- cgit From a1c3f33d94d7c40f3511e8dafde839ef0915d9a3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Nov 2000 19:14:10 +0000 Subject: Removed unnessesary init. Jeremy. (This used to be commit 2a797f9aa26b2d0c703b9d67f6e1ec97e4f408d2) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 4c885f34f1..8200c277b3 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -218,7 +218,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised = False; + static BOOL initialised; if (!lp_stat_cache()) return True; if (!initialised) { -- cgit From 9c54ddc7f9adeb63b5bc83fb7cd1b90bf0faf6ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 12 May 2001 13:04:15 +0000 Subject: statcache initialisation fix pointed out by Elrond (This used to be commit 572a37534b7ee010aafd7e8bcb9da52957306f97) --- source3/smbd/statcache.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8200c277b3..65a4830016 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -221,11 +221,11 @@ BOOL reset_stat_cache( void ) static BOOL initialised; if (!lp_stat_cache()) return True; - if (!initialised) { - initialised = True; - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + if (initialised) { + hash_clear(&stat_cache); } - hash_clear(&stat_cache); - return hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); + initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, + (compare_function)(strcmp)); + return initialised; } /* reset_stat_cache */ -- cgit From 527e824293ee934ca5da0ef5424efe5ab7757248 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 4 Jul 2001 07:36:09 +0000 Subject: strchr and strrchr are macros when compiling with optimisation in gcc, so we can't redefine them. damn. (This used to be commit c41fc06376d1a2b83690612304e85010b5e5f3cf) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 65a4830016..2e31e1252e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -174,7 +174,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, /* * Didn't find it - remove last component for next try. */ - sp = strrchr(chk_name, '/'); + sp = strrchr_m(chk_name, '/'); if (sp) { *sp = '\0'; } else { -- cgit From 827e1897783161a2a5ba797c0ff8727bd33a6f54 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 25 Sep 2001 06:38:07 +0000 Subject: fixed a typo (This used to be commit 11a2808e10bb7885da04c19c261d3876c31ac08d) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 2e31e1252e..09aa63d56d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -3,7 +3,7 @@ Version 3.0 stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-200 + Copyright (C) Jeremy Allison 1999-2000 This program is free software; you can redistribute it and/or modify -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/smbd/statcache.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 09aa63d56d..93782b9bb0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2000 -- cgit From 8a20407442efa0f9fe43e1b1c61140a0771c6ff8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 10 Feb 2003 11:47:21 +0000 Subject: Cleanups: (merge from HEAD) - use safe_strcpy() instead of pstrcpy() for malloc()ed strings - CUPS: a failure in an attempt to automaticly add a printer is not level 0 stuff. - Fix up a possible Realloc() failure segfault Andrew Bartlett (This used to be commit c1cfc296c2efdb2b5972202146e80f0e3b6a3da4) --- source3/smbd/statcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 93782b9bb0..f4b613428a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -122,8 +122,8 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) DEBUG(0,("stat_cache_add: Out of memory !\n")); return; } - pstrcpy(scp->names, orig_name); - pstrcpy(scp->names+namelen+1, translated_path); + safe_strcpy(scp->names, orig_name, namelen); + safe_strcpy(scp->names+namelen+1, translated_path, namelen); scp->name_len = namelen; hash_insert(&stat_cache, (char *)scp, orig_name); } -- cgit From c320f72f430d09bddbbf640feb8ee64b13e66f73 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 17 Mar 2003 22:23:51 +0000 Subject: Merge new statcache.c from HEAD. (This used to be commit 3b9db928fcaec322698d046db3a8a042b9a1d30c) --- source3/smbd/statcache.c | 187 +++++++++++++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 61 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index f4b613428a..0f42a3a83f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -3,7 +3,7 @@ stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2000 - + Copyright (C) Andrew Bartlett 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,30 +30,41 @@ extern BOOL case_sensitive; *****************************************************************************/ typedef struct { - int name_len; - char names[2]; /* This is extended via malloc... */ + char *original_path; + char *translated_path; + size_t translated_path_length; + char names[2]; /* This is extended via malloc... */ } stat_cache_entry; #define INIT_STAT_CACHE_SIZE 512 static hash_table stat_cache; -/**************************************************************************** - Add an entry into the stat cache. -*****************************************************************************/ +/** + * Add an entry into the stat cache. + * + * @param full_orig_name The original name as specified by the client + * @param orig_translated_path The name on our filesystem. + * + * @note Only the first strlen(orig_translated_path) characters are stored + * into the cache. This means that full_orig_name will be internally + * truncated. + * + */ -void stat_cache_add( char *full_orig_name, char *orig_translated_path) +void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) { stat_cache_entry *scp; stat_cache_entry *found_scp; - pstring orig_name; - pstring translated_path; - int namelen; + char *translated_path; + size_t translated_path_length; + + char *original_path; + size_t original_path_length; + hash_element *hash_elem; if (!lp_stat_cache()) return; - namelen = strlen(orig_translated_path); - /* * Don't cache trivial valid directory entries. */ @@ -62,7 +73,7 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) return; /* - * If we are in case insentive mode, we need to + * If we are in case insentive mode, we don't need to * store names that need no translation - else, it * would be a waste. */ @@ -75,74 +86,126 @@ void stat_cache_add( char *full_orig_name, char *orig_translated_path) * translated path. */ - pstrcpy(translated_path, orig_translated_path); - if(translated_path[namelen-1] == '/') { - translated_path[namelen-1] = '\0'; - namelen--; + translated_path = strdup(orig_translated_path); + if (!translated_path) + return; + + translated_path_length = strlen(translated_path); + + if(translated_path[translated_path_length-1] == '/') { + translated_path[translated_path_length-1] = '\0'; + translated_path_length--; } + original_path = strdup(full_orig_name); + if (!original_path) { + SAFE_FREE(translated_path); + return; + } + + original_path_length = strlen(original_path); + + if(original_path[original_path_length-1] == '/') { + original_path[original_path_length-1] = '\0'; + original_path_length--; + } + + if(!case_sensitive) + strupper(original_path); + + if (original_path_length != translated_path_length) { + if (original_path_length < translated_path_length) { + DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + /* we only want to store the first part of original_path, + up to the length of translated_path */ + + original_path[translated_path_length] = '\0'; + original_path_length = translated_path_length; + } + +#if 0 /* * We will only replace namelen characters * of full_orig_name. * StrnCpy always null terminates. */ - StrnCpy(orig_name, full_orig_name, namelen); + smbStrnCpy(orig_name, full_orig_name, namelen); if(!case_sensitive) strupper( orig_name ); +#endif /* * Check this name doesn't exist in the cache before we * add it. */ - if ((hash_elem = hash_lookup(&stat_cache, orig_name))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->names+found_scp->name_len+1), translated_path) == 0) { - return; - } else { - hash_remove(&stat_cache, hash_elem); - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - pstrcpy(scp->names, orig_name); - pstrcpy((scp->names+namelen+1), translated_path); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } - return; - } else { + if ((hash_elem = hash_lookup(&stat_cache, original_path))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { + /* already in hash table */ + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + /* hash collision - remove before we re-add */ + hash_remove(&stat_cache, hash_elem); + } + + /* + * New entry. + */ + + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) + +original_path_length + +translated_path_length)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } - /* - * New entry. - */ + scp->original_path = scp->names; + scp->translated_path = scp->names + original_path_length + 1; + safe_strcpy(scp->original_path, original_path, original_path_length); + safe_strcpy(scp->translated_path, translated_path, translated_path_length); + scp->translated_path_length = translated_path_length; - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)+2*namelen)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - return; - } - safe_strcpy(scp->names, orig_name, namelen); - safe_strcpy(scp->names+namelen+1, translated_path, namelen); - scp->name_len = namelen; - hash_insert(&stat_cache, (char *)scp, orig_name); - } + hash_insert(&stat_cache, (char *)scp, original_path); - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->names, (scp->names+scp->name_len+1))); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } -/**************************************************************************** - Look through the stat cache for an entry - promote it to the top if found. - Return True if we translated (and did a scuccessful stat on) the entire name. -*****************************************************************************/ +/** + * Look through the stat cache for an entry + * + * The hash-table's internals will promote it to the top if found. + * + * @param conn A connection struct to do the stat() with. + * @param name The path we are attempting to cache, modified by this routine + * to be correct as far as the cache can tell us + * @param dirpath The path as far as the stat cache told us. + * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. + * @param psd A stat buffer, NOT from the cache, but just a side-effect. + * + * @return True if we translated (and did a scuccessful stat on) the entire name. + * + */ -BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, +BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - char *trans_name; pstring chk_name; - int namelen; + size_t namelen; hash_element *hash_elem; char *sp; @@ -191,18 +254,20 @@ BOOL stat_cache_lookup(connection_struct *conn, char *name, char *dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - trans_name = scp->names+scp->name_len+1; - if(vfs_stat(conn,trans_name, pst) != 0) { + if(vfs_stat(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; } - memcpy(name, trans_name, scp->name_len); - *start = &name[scp->name_len]; + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[scp->translated_path_length]; if(**start == '/') ++*start; - StrnCpy( dirpath, trans_name, name - (*start)); - return (namelen == scp->name_len); + + pstrcpy(dirpath, scp->translated_path); + return (namelen == scp->translated_path_length); } } } -- cgit From 2a3a9f0bf43c3bf99a71f7296bb5ff6199893fea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Apr 2003 13:27:35 +0000 Subject: Merge the 'safe' parts of my StrnCpy patch - many of the users really wanted a pstrcpy/fstrcpy or at most a safe_strcpy(). These have the advantage of being compiler-verifiable. Get these out of the way, along with a rewrite of 'get_short_archi' in the spoolss client and server. (This pushes around const string pointers, rather than copied strings). Andrew Bartlett (This used to be commit 32fb801ddc035e8971e9911ed4b6e51892e9d1cc) --- source3/smbd/statcache.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 0f42a3a83f..44bae48990 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -128,18 +128,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length = translated_path_length; } -#if 0 - /* - * We will only replace namelen characters - * of full_orig_name. - * StrnCpy always null terminates. - */ - - smbStrnCpy(orig_name, full_orig_name, namelen); - if(!case_sensitive) - strupper( orig_name ); -#endif - /* * Check this name doesn't exist in the cache before we * add it. -- cgit From e7c8c15888454043c73967635deb4d3419a489e9 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 11 May 2003 23:34:18 +0000 Subject: Fix VFS layer: 1. Finally work with cascaded modules with private data storage per module 2. Convert VFS API to macro calls to simplify cascading 3. Add quota support to VFS layer (prepare to NT quota support) Patch by Stefan (metze) Metzemacher, with review of Jelmer and me Tested in past few weeks. Documentation to new VFS API for third-party developers to follow (This used to be commit 91984ef5caa2d13c5d52e1f535bd3bbbae1ec978) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 44bae48990..5c77474fec 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - if(vfs_stat(conn,scp->translated_path, pst) != 0) { + if(VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; -- cgit From bc2a3748e9caa8f60f7c2387e7eecd7fb3fae899 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 14 May 2003 10:59:01 +0000 Subject: Prefix VFS API macros with SMB_ for consistency and to avoid problems with VFS_ macros at system side. We currently have one clash with AIX and its VFS_LOCK. Compiled and tested -- no new functionality or code, just plain rename of macros for yet-unreleased VFS API version. Needs to be done before a24 is out (This used to be commit c2689ed118b490e49497a76ed6a2251262018769) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5c77474fec..79758bcfe2 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } else { scp = (stat_cache_entry *)(hash_elem->value); DO_PROFILE_INC(statcache_hits); - if(VFS_STAT(conn,scp->translated_path, pst) != 0) { + if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); return False; -- cgit From b55b664539eec149ea912d22de8fe0969f0a43cd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jul 2003 00:08:29 +0000 Subject: Whitespace reformat before applying a patch. Jeremy. (This used to be commit bbe1276b516e1803a4a9285691674784b989b72f) --- source3/smbd/statcache.c | 371 ++++++++++++++++++++++++----------------------- 1 file changed, 187 insertions(+), 184 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 79758bcfe2..0d55c22f7a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -24,7 +24,6 @@ extern BOOL case_sensitive; - /**************************************************************************** Stat cache code used in unix_convert. *****************************************************************************/ @@ -53,123 +52,126 @@ static hash_table stat_cache; void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) { - stat_cache_entry *scp; - stat_cache_entry *found_scp; - char *translated_path; - size_t translated_path_length; - - char *original_path; - size_t original_path_length; - - hash_element *hash_elem; - - if (!lp_stat_cache()) return; - - /* - * Don't cache trivial valid directory entries. - */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) - return; - - /* - * If we are in case insentive mode, we don't need to - * store names that need no translation - else, it - * would be a waste. - */ - - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) - return; - - /* - * Remove any trailing '/' characters from the - * translated path. - */ - - translated_path = strdup(orig_translated_path); - if (!translated_path) - return; - - translated_path_length = strlen(translated_path); - - if(translated_path[translated_path_length-1] == '/') { - translated_path[translated_path_length-1] = '\0'; - translated_path_length--; - } - - original_path = strdup(full_orig_name); - if (!original_path) { - SAFE_FREE(translated_path); - return; - } - - original_path_length = strlen(original_path); - - if(original_path[original_path_length-1] == '/') { - original_path[original_path_length-1] = '\0'; - original_path_length--; - } - - if(!case_sensitive) - strupper(original_path); - - if (original_path_length != translated_path_length) { - if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - /* we only want to store the first part of original_path, - up to the length of translated_path */ - - original_path[translated_path_length] = '\0'; - original_path_length = translated_path_length; - } - - /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, original_path))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { - /* already in hash table */ - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - /* hash collision - remove before we re-add */ - hash_remove(&stat_cache, hash_elem); - } + stat_cache_entry *scp; + stat_cache_entry *found_scp; + char *translated_path; + size_t translated_path_length; + + char *original_path; + size_t original_path_length; + + hash_element *hash_elem; + + if (!lp_stat_cache()) + return; + + /* + * Don't cache trivial valid directory entries. + */ + + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) + return; + + /* + * If we are in case insentive mode, we don't need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + translated_path = strdup(orig_translated_path); + if (!translated_path) + return; + + translated_path_length = strlen(translated_path); + + if(translated_path[translated_path_length-1] == '/') { + translated_path[translated_path_length-1] = '\0'; + translated_path_length--; + } + + original_path = strdup(full_orig_name); + if (!original_path) { + SAFE_FREE(translated_path); + return; + } + + original_path_length = strlen(original_path); + + if(original_path[original_path_length-1] == '/') { + original_path[original_path_length-1] = '\0'; + original_path_length--; + } + + if(!case_sensitive) + strupper(original_path); + + if (original_path_length != translated_path_length) { + if (original_path_length < translated_path_length) { + DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + original_path, original_path_length, translated_path, translated_path_length)); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + /* we only want to store the first part of original_path, + up to the length of translated_path */ + + original_path[translated_path_length] = '\0'; + original_path_length = translated_path_length; + } + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + if ((hash_elem = hash_lookup(&stat_cache, original_path))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { + /* already in hash table */ + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + /* hash collision - remove before we re-add */ + hash_remove(&stat_cache, hash_elem); + } - /* - * New entry. - */ + /* + * New entry. + */ - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) - +original_path_length - +translated_path_length)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - scp->original_path = scp->names; - scp->translated_path = scp->names + original_path_length + 1; - safe_strcpy(scp->original_path, original_path, original_path_length); - safe_strcpy(scp->translated_path, translated_path, translated_path_length); - scp->translated_path_length = translated_path_length; - - hash_insert(&stat_cache, (char *)scp, original_path); - - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) + +original_path_length + +translated_path_length)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + scp->original_path = scp->names; + scp->translated_path = scp->names + original_path_length + 1; + safe_strcpy(scp->original_path, original_path, original_path_length); + safe_strcpy(scp->translated_path, translated_path, translated_path_length); + scp->translated_path_length = translated_path_length; + + hash_insert(&stat_cache, (char *)scp, original_path); + + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } /** @@ -191,73 +193,73 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { - stat_cache_entry *scp; - pstring chk_name; - size_t namelen; - hash_element *hash_elem; - char *sp; - - if (!lp_stat_cache()) - return False; + stat_cache_entry *scp; + pstring chk_name; + size_t namelen; + hash_element *hash_elem; + char *sp; + + if (!lp_stat_cache()) + return False; - namelen = strlen(name); - - *start = name; - - DO_PROFILE_INC(statcache_lookups); - - /* - * Don't lookup trivial valid directory entries. - */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - - pstrcpy(chk_name, name); - if(!case_sensitive) - strupper( chk_name ); - - while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { - /* - * Didn't find it - remove last component for next try. - */ - sp = strrchr_m(chk_name, '/'); - if (sp) { - *sp = '\0'; - } else { - /* - * We reached the end of the name - no match. - */ - DO_PROFILE_INC(statcache_misses); - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - } else { - scp = (stat_cache_entry *)(hash_elem->value); - DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); - return False; - } - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); - - /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[scp->translated_path_length]; - if(**start == '/') - ++*start; - - pstrcpy(dirpath, scp->translated_path); - return (namelen == scp->translated_path_length); - } - } + namelen = strlen(name); + + *start = name; + + DO_PROFILE_INC(statcache_lookups); + + /* + * Don't lookup trivial valid directory entries. + */ + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + + pstrcpy(chk_name, name); + if(!case_sensitive) + strupper( chk_name ); + + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr_m(chk_name, '/'); + if (sp) { + *sp = '\0'; + } else { + /* + * We reached the end of the name - no match. + */ + DO_PROFILE_INC(statcache_misses); + return False; + } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + DO_PROFILE_INC(statcache_hits); + if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[scp->translated_path_length]; + if(**start == '/') + ++*start; + + pstrcpy(dirpath, scp->translated_path); + return (namelen == scp->translated_path_length); + } + } } /*************************************************************************** ** @@ -271,7 +273,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, BOOL reset_stat_cache( void ) { static BOOL initialised; - if (!lp_stat_cache()) return True; + if (!lp_stat_cache()) + return True; if (initialised) { hash_clear(&stat_cache); @@ -280,4 +283,4 @@ BOOL reset_stat_cache( void ) initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); return initialised; -} /* reset_stat_cache */ +} -- cgit From af4d65889420eb3bb71be67d619dbc0c62e21101 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Jul 2003 20:01:51 +0000 Subject: Added fix for Japanese case names in statcache - these can change size on upper casing. Based on patch from monyo@home.monyo.com. Jeremy. (This used to be commit 72e382e99b92666acdaf50a040b14aa16d48b80d) --- source3/smbd/statcache.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 0d55c22f7a..593df745cc 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -198,6 +198,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, size_t namelen; hash_element *hash_elem; char *sp; + BOOL sizechanged = False; + unsigned int num_components = 0; if (!lp_stat_cache()) return False; @@ -217,8 +219,17 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } pstrcpy(chk_name, name); - if(!case_sensitive) + + if(!case_sensitive) { strupper( chk_name ); + /* + * In some language encodings the length changes + * if we uppercase. We need to treat this differently + * below. + */ + if (strlen(chk_name) != namelen) + sizechanged = True; + } while (1) { hash_elem = hash_lookup(&stat_cache, chk_name); @@ -229,6 +240,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, sp = strrchr_m(chk_name, '/'); if (sp) { *sp = '\0'; + /* + * Count the number of times we have done this, + * we'll need it when reconstructing the string. + */ + if (sizechanged) + num_components++; + } else { /* * We reached the end of the name - no match. @@ -249,7 +267,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, hash_remove(&stat_cache, hash_elem); return False; } - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + + if (!sizechanged) { + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + } else { + pstring last_component; + sp = strnrchr_m(name, '/', num_components); + if (!sp) { + /* Logic error. */ + smb_panic("logic error in stat_cache_lookup\n"); + } + pstrcpy(last_component, sp); + pstrcpy(name, scp->translated_path); + pstrcat(name, last_component); + } /* set pointer for 'where to start' on fixing the rest of the name */ *start = &name[scp->translated_path_length]; -- cgit From ce72beb2b558d86fb49063c6b1fa00e07952ce56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jul 2003 19:11:31 +0000 Subject: Removed strupper/strlower macros that automatically map to strupper_m/strlower_m. I really want people to think about when they're using multibyte strings. Jeremy. (This used to be commit ff222716a08af65d26ad842ce4c2841cc6540959) --- source3/smbd/statcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 593df745cc..5d54a5c4ff 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -112,7 +112,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if(!case_sensitive) - strupper(original_path); + strupper_m(original_path); if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { @@ -221,7 +221,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, pstrcpy(chk_name, name); if(!case_sensitive) { - strupper( chk_name ); + strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently -- cgit From 45ac30db09332bc5de20ea15cc07c25ebc6fb6f7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 7 Jul 2003 20:22:35 +0000 Subject: Fix from MORIYAMA Masayuki for new MB statcache code. Bug #185. Jeremy. (This used to be commit 7a1ac7be42dfb90fd44f2c51810eedcea052386b) --- source3/smbd/statcache.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5d54a5c4ff..22b8a33a1e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -270,16 +270,18 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if (!sizechanged) { memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + } else if (num_components == 0) { + pstrcpy(name, scp->translated_path); } else { - pstring last_component; sp = strnrchr_m(name, '/', num_components); - if (!sp) { - /* Logic error. */ - smb_panic("logic error in stat_cache_lookup\n"); + if (sp) { + pstring last_component; + pstrcpy(last_component, sp); + pstrcpy(name, scp->translated_path); + pstrcat(name, last_component); + } else { + pstrcpy(name, scp->translated_path); } - pstrcpy(last_component, sp); - pstrcpy(name, scp->translated_path); - pstrcat(name, last_component); } /* set pointer for 'where to start' on fixing the rest of the name */ -- cgit From 5b84b13a1e2f47fbd5ca710721cdb9b3f10727e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 27 Jul 2003 03:40:45 +0000 Subject: Allow the stat cache to better handle invalid multibyte strings, by using strdup_upper(). This function may fail - and we can just drop out of using the cache in that case. (Rather than panicing). This also should get us closer to supporting all of the weird 'longer/shorter' on uppercase/lowercase. Andrew Bartlett (This used to be commit d4c9261725578231079ed83e8e6584f12bd1cc43) --- source3/smbd/statcache.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 22b8a33a1e..fbebdb240f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -98,7 +98,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat translated_path_length--; } - original_path = strdup(full_orig_name); + if(case_sensitive) { + original_path = strdup(full_orig_name); + } else { + original_path = strdup_upper(full_orig_name); + } + if (!original_path) { SAFE_FREE(translated_path); return; @@ -111,9 +116,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length--; } - if(!case_sensitive) - strupper_m(original_path); - if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", @@ -161,6 +163,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } scp->original_path = scp->names; + /* pointer into the structure... */ scp->translated_path = scp->names + original_path_length + 1; safe_strcpy(scp->original_path, original_path, original_path_length); safe_strcpy(scp->translated_path, translated_path, translated_path_length); @@ -194,7 +197,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - pstring chk_name; + char *chk_name; size_t namelen; hash_element *hash_elem; char *sp; @@ -218,10 +221,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } - pstrcpy(chk_name, name); + if (case_sensitive) { + chk_name = strdup(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); + return False; + } + + } else { + chk_name = strdup_upper(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); + return False; + } - if(!case_sensitive) { - strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently @@ -252,11 +265,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } } else { @@ -265,6 +280,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); + SAFE_FREE(chk_name); return False; } @@ -290,6 +306,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, ++*start; pstrcpy(dirpath, scp->translated_path); + SAFE_FREE(chk_name); return (namelen == scp->translated_path_length); } } -- cgit From 94f59f54921174fc156fade575ca114d331b1bd8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2003 19:59:55 +0000 Subject: More tuning from cachegrind. Change most trim_string() calls to trim_char(0, as that's what they do. Fix string_replace() to fast-path ascii. Jeremy. (This used to be commit f35e9a8b909d3c74be47083ccc4a4e91a14938db) --- source3/smbd/statcache.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index fbebdb240f..28915a30a0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -66,11 +66,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat return; /* - * Don't cache trivial valid directory entries. + * Don't cache trivial valid directory entries such as . and .. */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) + if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && + ((full_orig_name[1] == '\0') || + (full_orig_name[1] == '.' && full_orig_name[1] == '\0')))) return; /* -- cgit From 966b0fc7c96b1dba63fa755312a2be64e18ff471 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 2003 21:30:50 +0000 Subject: More cachegrind tuning, plus fix an error message. Jeremy. (This used to be commit 8cb9ec5d533085d40fc6bfe4ca9647d80bf41ac7) --- source3/smbd/statcache.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 28915a30a0..948173687d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -217,10 +217,10 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, /* * Don't lookup trivial valid directory entries. */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); + if((*name == '\0') || (name[0] == '.' && + ((name[1] == '\0') || + (name[1] == '.' && name[1] == '\0')))) return False; - } if (case_sensitive) { chk_name = strdup(name); @@ -248,6 +248,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, while (1) { hash_elem = hash_lookup(&stat_cache, chk_name); if(hash_elem == NULL) { + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. */ @@ -277,6 +278,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } else { scp = (stat_cache_entry *)(hash_elem->value); + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path )); DO_PROFILE_INC(statcache_hits); if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ -- cgit From abdc2695e21285816bbcbf829560023a36b26ee8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 12:22:34 +0000 Subject: Fixed typo in debug. (This used to be commit e2b5dd7d9b351984c40876f3c86f2a006e0eec42) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 948173687d..76406f208e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -119,7 +119,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); SAFE_FREE(original_path); SAFE_FREE(translated_path); -- cgit From fbb8f131c2336e921677f41e9fb8bce7406f3336 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 3 Nov 2003 14:34:25 +0000 Subject: Fix more 64-bit printf warnings. (This used to be commit 23443e3aa079710221557e18158d0ddb8ff48a36) --- source3/smbd/statcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 76406f208e..d996f5e493 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -119,8 +119,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %u and [%s] %u)!\n", - original_path, original_path_length, translated_path, translated_path_length)); + DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", + original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); SAFE_FREE(original_path); SAFE_FREE(translated_path); return; -- cgit From e0da56a84808c522bc7324b5d636f1cbd317a2c5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 May 2004 18:37:47 +0000 Subject: r570: Remove lots of globals to handle case issues - move them to connection struct entries (as they should have been from the start). Jerry, once you've cut over to 3.0.4 release branch I'll add this to 3.0 also. - Jerry cut over :-). Jeremy. (This used to be commit 578a508509d21226ad3332fc54c3ab54cd8ae452) --- source3/smbd/statcache.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index d996f5e493..5e78e9a499 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -22,8 +22,6 @@ #include "includes.h" -extern BOOL case_sensitive; - /**************************************************************************** Stat cache code used in unix_convert. *****************************************************************************/ @@ -50,7 +48,7 @@ static hash_table stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) +void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) { stat_cache_entry *scp; stat_cache_entry *found_scp; @@ -222,7 +220,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, (name[1] == '.' && name[1] == '\0')))) return False; - if (case_sensitive) { + if (conn->case_sensitive) { chk_name = strdup(name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); -- cgit From fcbb2d3132df36057da73701f7e23f434034e6b0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 24 Aug 2004 22:48:49 +0000 Subject: r2026: Simplify statcache to use an in-memory tdb. Modify tdb to use a customer hash function for this tdb (yes it does make a difference on benchmarks). Remove the no longer used hash.c code. Jeremy. (This used to be commit 3fbadac85b8cad89b93d295968e99c38c8677575) --- source3/smbd/statcache.c | 140 ++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 75 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 5e78e9a499..07a9e3ca85 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -26,15 +26,7 @@ Stat cache code used in unix_convert. *****************************************************************************/ -typedef struct { - char *original_path; - char *translated_path; - size_t translated_path_length; - char names[2]; /* This is extended via malloc... */ -} stat_cache_entry; - -#define INIT_STAT_CACHE_SIZE 512 -static hash_table stat_cache; +static TDB_CONTEXT *tdb_stat_cache; /** * Add an entry into the stat cache. @@ -50,19 +42,17 @@ static hash_table stat_cache; void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) { - stat_cache_entry *scp; - stat_cache_entry *found_scp; char *translated_path; size_t translated_path_length; - + TDB_DATA data_val; char *original_path; size_t original_path_length; - hash_element *hash_elem; - if (!lp_stat_cache()) return; + ZERO_STRUCT(data_val); + /* * Don't cache trivial valid directory entries such as . and .. */ @@ -124,7 +114,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat return; } - /* we only want to store the first part of original_path, + /* we only want to index by the first part of original_path, up to the length of translated_path */ original_path[translated_path_length] = '\0'; @@ -132,55 +122,26 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, original_path))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { - /* already in hash table */ - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - /* hash collision - remove before we re-add */ - hash_remove(&stat_cache, hash_elem); - } - - /* - * New entry. + * New entry or replace old entry. */ - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) - +original_path_length - +translated_path_length)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - scp->original_path = scp->names; - /* pointer into the structure... */ - scp->translated_path = scp->names + original_path_length + 1; - safe_strcpy(scp->original_path, original_path, original_path_length); - safe_strcpy(scp->translated_path, translated_path, translated_path_length); - scp->translated_path_length = translated_path_length; + data_val.dsize = translated_path_length + 1; + data_val.dptr = translated_path; - hash_insert(&stat_cache, (char *)scp, original_path); + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { + DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); + } else { + DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n", + (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path)); + } SAFE_FREE(original_path); SAFE_FREE(translated_path); - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } /** * Look through the stat cache for an entry * - * The hash-table's internals will promote it to the top if found. - * * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine * to be correct as far as the cache can tell us @@ -195,11 +156,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { - stat_cache_entry *scp; char *chk_name; size_t namelen; - hash_element *hash_elem; - char *sp; BOOL sizechanged = False; unsigned int num_components = 0; @@ -244,8 +202,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { + TDB_DATA data_val; + char *sp; + + data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); + if(data_val.dptr == NULL || data_val.dsize == 0) { DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. @@ -275,44 +236,71 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } } else { - scp = (stat_cache_entry *)(hash_elem->value); - DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path )); + BOOL retval; + char *translated_path = data_val.dptr; + size_t translated_path_length = data_val.dsize - 1; + + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { + if(SMB_VFS_STAT(conn,translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); + tdb_delete_bystring(tdb_stat_cache, chk_name); SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); return False; } if (!sizechanged) { - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length)); } else if (num_components == 0) { - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); } else { sp = strnrchr_m(name, '/', num_components); if (sp) { pstring last_component; pstrcpy(last_component, sp); - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); pstrcat(name, last_component); } else { - pstrcpy(name, scp->translated_path); + pstrcpy(name, translated_path); } } /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[scp->translated_path_length]; + *start = &name[translated_path_length]; if(**start == '/') ++*start; - pstrcpy(dirpath, scp->translated_path); + pstrcpy(dirpath, translated_path); + retval = (namelen == translated_path_length) ? True : False; SAFE_FREE(chk_name); - return (namelen == scp->translated_path_length); + SAFE_FREE(data_val.dptr); + return retval; } } } +/* + ************************************************************** + * Compute a hash value based on a string key value. + * Make the string key into an array of int's if possible. + * For the last few chars that cannot be int'ed, use char instead. + * The function returns the bucket index number for the hashed + * key. + * JRA. Use a djb-algorithm hash for speed. + ************************************************************** + */ + +static u32 string_hash(TDB_DATA *key) +{ + u32 n = 0; + const char *p; + for (p = key->dptr; *p != '\0'; p++) { + n = ((n << 5) + n) ^ (u32)(*p); + } + return n; +} + /*************************************************************************** ** * Initializes or clears the stat cache. * @@ -323,15 +311,17 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, */ BOOL reset_stat_cache( void ) { - static BOOL initialised; if (!lp_stat_cache()) return True; - if (initialised) { - hash_clear(&stat_cache); + if (tdb_stat_cache) { + tdb_close(tdb_stat_cache); } - initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, - (compare_function)(strcmp)); - return initialised; + /* Create the in-memory tdb. */ + tdb_stat_cache = tdb_open_log("statcache", 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); + if (!tdb_stat_cache) + return False; + tdb_set_hash_function(tdb_stat_cache, string_hash); + return True; } -- cgit From f98af01f43d37d9d633ec8861232fc1c7f66d3f9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 25 Aug 2004 01:04:02 +0000 Subject: r2032: If you're selecting a hash algorithm for tdb, you need to do it at open time, it doesn't make sense anywhere else. Jeremy. (This used to be commit d7ea1ea8fb3420ca1ad8d95acdc43313898200ff) --- source3/smbd/statcache.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 07a9e3ca85..dfc1a6ed95 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-2000 + Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 This program is free software; you can redistribute it and/or modify @@ -280,16 +280,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } -/* - ************************************************************** - * Compute a hash value based on a string key value. - * Make the string key into an array of int's if possible. - * For the last few chars that cannot be int'ed, use char instead. - * The function returns the bucket index number for the hashed - * key. - * JRA. Use a djb-algorithm hash for speed. - ************************************************************** - */ +/*************************************************************** + Compute a hash value based on a string key value. + The function returns the bucket index number for the hashed key. + JRA. Use a djb-algorithm hash for speed. +***************************************************************/ static u32 string_hash(TDB_DATA *key) { @@ -301,14 +296,10 @@ static u32 string_hash(TDB_DATA *key) return n; } -/*************************************************************************** ** - * Initializes or clears the stat cache. - * - * Input: none. - * Output: none. - * - * ************************************************************************** ** - */ +/*************************************************************************** + Initializes or clears the stat cache. +**************************************************************************/ + BOOL reset_stat_cache( void ) { if (!lp_stat_cache()) @@ -318,10 +309,11 @@ BOOL reset_stat_cache( void ) tdb_close(tdb_stat_cache); } - /* Create the in-memory tdb. */ - tdb_stat_cache = tdb_open_log("statcache", 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644); + /* Create the in-memory tdb using our custom hash function. */ + tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, + (O_RDWR|O_CREAT), 0644, NULL, string_hash); + if (!tdb_stat_cache) return False; - tdb_set_hash_function(tdb_stat_cache, string_hash); return True; } -- cgit From f1688d61df13aacb0e512fd16504cc94f803d808 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Aug 2004 20:19:40 +0000 Subject: r2112: Simplify the mangle hash code to use an in-memory tdb. Should be ready for the new directory code now... Jeremy. (This used to be commit c2eff8ef1b65570d2e590f62f026cc18f9142652) --- source3/smbd/statcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index dfc1a6ed95..03adf32e09 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -286,7 +286,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -static u32 string_hash(TDB_DATA *key) +u32 fast_string_hash(TDB_DATA *key) { u32 n = 0; const char *p; @@ -311,7 +311,7 @@ BOOL reset_stat_cache( void ) /* Create the in-memory tdb using our custom hash function. */ tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, string_hash); + (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) return False; -- cgit From 1d7f22c9ae9c18854fe47f7bd51355fced76201c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Aug 2004 22:25:36 +0000 Subject: r2116: Ensure statcache has large enough tdb memory hash size (1031). Jeremy. (This used to be commit dad4d65787df7bd28351cb8f8724d3ae5387ca12) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 03adf32e09..ba37d4927c 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -310,7 +310,7 @@ BOOL reset_stat_cache( void ) } /* Create the in-memory tdb using our custom hash function. */ - tdb_stat_cache = tdb_open_ex("statcache", 0, TDB_INTERNAL, + tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/statcache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index ba37d4927c..cfc5286327 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -76,7 +76,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * translated path. */ - translated_path = strdup(orig_translated_path); + translated_path = SMB_STRDUP(orig_translated_path); if (!translated_path) return; @@ -88,7 +88,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if(case_sensitive) { - original_path = strdup(full_orig_name); + original_path = SMB_STRDUP(full_orig_name); } else { original_path = strdup_upper(full_orig_name); } @@ -179,7 +179,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; if (conn->case_sensitive) { - chk_name = strdup(name); + chk_name = SMB_STRDUP(name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); return False; -- cgit From ecc6933a86dfc61b49ce907cf444cc45d2e3f8d5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Apr 2005 20:59:37 +0000 Subject: r6240: Fix for bug #2581. Add size limit (in kb) to stat cache. Jeremy. (This used to be commit 836b73d0018c3137b7a924b6345e69ae5d23431d) --- source3/smbd/statcache.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index cfc5286327..99f209006b 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -47,10 +47,15 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat TDB_DATA data_val; char *original_path; size_t original_path_length; + size_t sc_size = lp_max_stat_cache_size(); if (!lp_stat_cache()) return; + if (sc_size && (sc_size*1024 > tdb_stat_cache->map_size)) { + reset_stat_cache(); + } + ZERO_STRUCT(data_val); /* -- cgit From 43710a45e8308afac43d8ad1bf6f1aab05a77bb9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 8 Apr 2005 17:04:59 +0000 Subject: r6249: Get the comparison the right way around... Jeremy. (This used to be commit 1d542eee571b80259568d49bd5dc2eb14fd80d01) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 99f209006b..8e22d9687b 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (!lp_stat_cache()) return; - if (sc_size && (sc_size*1024 > tdb_stat_cache->map_size)) { + if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { reset_stat_cache(); } -- cgit From 81ee9412854fe57124144a1337f2e6680d1afd80 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 23 Jun 2005 17:00:11 +0000 Subject: r7846: Fix from bugzilla@kevinjamieson.com Kevin Jamieson - typo in checking for .. in statcache. Bugid #2819. Jeremy. (This used to be commit a5619d717954ad2a3ffaa549b11bfa738720e325) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8e22d9687b..97ecd4152c 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -64,7 +64,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && ((full_orig_name[1] == '\0') || - (full_orig_name[1] == '.' && full_orig_name[1] == '\0')))) + (full_orig_name[1] == '.' && full_orig_name[2] == '\0')))) return; /* -- cgit From ab59cdc5803371faa7fd2d983f3dc796afceb007 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Sep 2005 21:47:42 +0000 Subject: r10186: More 64-bit warning fixes. Jeremy. (This used to be commit 88034b9c2845a38833f300b812202c2a4ca3d2fd) --- source3/smbd/statcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 97ecd4152c..548d7c4a48 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -136,8 +136,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); } else { - DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n", - (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path)); + DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", + (unsigned long)data_val.dptr, (unsigned int)data_val.dsize, original_path, translated_path)); } SAFE_FREE(original_path); -- cgit From 4f240462949ca7487b111adf7aef249f4c6f6e8d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Apr 2006 12:23:38 +0000 Subject: r15102: u32 is a tdb-only thing that's not exported by samba4 tdb. Replace by uint32. Volker (This used to be commit 0a1665a1b78d063840e42e85229ace5a751e3985) --- source3/smbd/statcache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 548d7c4a48..fe022017b5 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -u32 fast_string_hash(TDB_DATA *key) +uint32 fast_string_hash(TDB_DATA *key) { - u32 n = 0; + uint32 n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (u32)(*p); + n = ((n << 5) + n) ^ (uint32)(*p); } return n; } -- cgit From 76e581b983989377d3ac3ae89b2b7d925aadc3f5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 17 Apr 2006 12:27:35 +0000 Subject: r15103: Okay, looking closer: Samba4 tdb not exporting u32 is a bug in samba4's tdb. tdb_open_ex needs it. Can someone from samba4 tell me how this should be handled? Thanks, Volker (This used to be commit 0a2f1ed5e9012e07ef158666b68994d0961768b6) --- source3/smbd/statcache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index fe022017b5..548d7c4a48 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -uint32 fast_string_hash(TDB_DATA *key) +u32 fast_string_hash(TDB_DATA *key) { - uint32 n = 0; + u32 n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (uint32)(*p); + n = ((n << 5) + n) ^ (u32)(*p); } return n; } -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/statcache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 548d7c4a48..b453fdd544 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -52,7 +52,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (!lp_stat_cache()) return; - if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { + if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { reset_stat_cache(); } @@ -291,12 +291,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, JRA. Use a djb-algorithm hash for speed. ***************************************************************/ -u32 fast_string_hash(TDB_DATA *key) +unsigned int fast_string_hash(TDB_DATA *key) { - u32 n = 0; + unsigned int n = 0; const char *p; for (p = key->dptr; *p != '\0'; p++) { - n = ((n << 5) + n) ^ (u32)(*p); + n = ((n << 5) + n) ^ (unsigned int)(*p); } return n; } -- cgit From aacd16e7c4bea5018560eea09d55f2a6473be84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Jan 2007 21:46:12 +0000 Subject: r20916: Add in the delete on close final fix - but only enabled with -DDEVELOPER. Jeremy. (This used to be commit 7f817067a70930ee3502ea3373173e0c23733253) --- source3/smbd/statcache.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b453fdd544..1a2b7a8237 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -285,6 +285,40 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } +/*************************************************************************** + Tell all smbd's to delete an entry. +**************************************************************************/ + +void send_stat_cache_delete_message(const char *name) +{ +#ifdef DEVELOPER + message_send_all(conn_tdb_ctx(), + MSG_SMB_STAT_CACHE_DELETE, + name, + strlen(name)+1, + True, + NULL); +#endif +} + +/*************************************************************************** + Delete an entry. +**************************************************************************/ + +void stat_cache_delete(const char *name) +{ + char *lname = strdup_upper(name); + + if (!lname) { + return; + } + DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n", + lname, name )); + + tdb_delete_bystring(tdb_stat_cache, lname); + SAFE_FREE(lname); +} + /*************************************************************** Compute a hash value based on a string key value. The function returns the bucket index number for the hashed key. -- cgit From bc2b6436d0f5f3e9ffdfaeb7f1b32996a83d5478 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Mar 2007 09:35:51 +0000 Subject: r22009: change TDB_DATA from char * to unsigned char * and fix all compiler warnings in the users metze (This used to be commit 3a28443079c141a6ce8182c65b56ca210e34f37f) --- source3/smbd/statcache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 1a2b7a8237..e257483f81 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -131,7 +131,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat */ data_val.dsize = translated_path_length + 1; - data_val.dptr = translated_path; + data_val.dptr = (uint8 *)translated_path; if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); @@ -242,7 +242,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } else { BOOL retval; - char *translated_path = data_val.dptr; + char *translated_path = (char *)data_val.dptr; size_t translated_path_length = data_val.dsize - 1; DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); @@ -329,7 +329,7 @@ unsigned int fast_string_hash(TDB_DATA *key) { unsigned int n = 0; const char *p; - for (p = key->dptr; *p != '\0'; p++) { + for (p = (const char *)key->dptr; *p != '\0'; p++) { n = ((n << 5) + n) ^ (unsigned int)(*p); } return n; -- cgit From 4aa44f7475e03dcc596f6a13fffffda7268074a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 8 May 2007 13:44:36 +0000 Subject: r22761: This introduces lib/conn_tdb.c with two main functions: connections_traverse and connections_forall. This centralizes all the routines that did individual tdb_open("connections.tdb") and direct tdb_traverse. Volker (This used to be commit e43e94cda1ad8876b3cb5d1129080b57fa6ec214) --- source3/smbd/statcache.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index e257483f81..7c2c968d8d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -292,8 +292,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, void send_stat_cache_delete_message(const char *name) { #ifdef DEVELOPER - message_send_all(conn_tdb_ctx(), - MSG_SMB_STAT_CACHE_DELETE, + message_send_all(MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, True, -- cgit From 8c3f8e5697f29f1a9829298e0561ff7305b62082 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 May 2007 15:49:55 +0000 Subject: r22911: Pass a messaging_context to message_send_all (This used to be commit cc92ce665dcfe9054d09429219883b18a4cab090) --- source3/smbd/statcache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 7c2c968d8d..1d6646257a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -292,7 +292,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, void send_stat_cache_delete_message(const char *name) { #ifdef DEVELOPER - message_send_all(MSG_SMB_STAT_CACHE_DELETE, + message_send_all(smbd_messaging_context(), + MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, True, -- cgit From ac3f08ddbe0b484375624db0e35999a8584b57f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 May 2007 22:17:13 +0000 Subject: r23055: Rewrite messages.c to use auto-generated marshalling in the tdb. I'm doing this because for the clustering the marshalling is needed in more than one place, so I wanted a decent routine to marshall a message_rec struct which was not there before. Tridge, this seems about the same speed as it used to be before, the librpc/ndr overhead in my tests was under the noise. Volker (This used to be commit eaefd00563173dfabb7716c5695ac0a2f7139bb6) --- source3/smbd/statcache.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 1d6646257a..b63dd165a7 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -296,7 +296,6 @@ void send_stat_cache_delete_message(const char *name) MSG_SMB_STAT_CACHE_DELETE, name, strlen(name)+1, - True, NULL); #endif } -- cgit From c35d814e393e4211e3f6e0dcaff76536c256ff6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 7 Jul 2007 09:57:27 +0000 Subject: r23743: Simplify stat_cache_lookup() logic. For the history of this, see http://article.gmane.org/gmane.network.samba.internals/32486. (This used to be commit e5e42fe3d5b26c0ec48d98c001b9cb1623c0b5a7) --- source3/smbd/statcache.c | 144 +++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 68 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index b63dd165a7..92c845ce2e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -165,6 +165,9 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, size_t namelen; BOOL sizechanged = False; unsigned int num_components = 0; + char *translated_path; + size_t translated_path_length; + TDB_DATA data_val; if (!lp_stat_cache()) return False; @@ -207,82 +210,87 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } while (1) { - TDB_DATA data_val; char *sp; data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); - if(data_val.dptr == NULL || data_val.dsize == 0) { - DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + + if (data_val.dptr != NULL && data_val.dsize != 0) { + break; + } + + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + /* + * Didn't find it - remove last component for next try. + */ + if (!(sp = strrchr_m(chk_name, '/'))) { /* - * Didn't find it - remove last component for next try. + * We reached the end of the name - no match. */ - sp = strrchr_m(chk_name, '/'); - if (sp) { - *sp = '\0'; - /* - * Count the number of times we have done this, - * we'll need it when reconstructing the string. - */ - if (sizechanged) - num_components++; - - } else { - /* - * We reached the end of the name - no match. - */ - DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); - return False; - } - } else { - BOOL retval; - char *translated_path = (char *)data_val.dptr; - size_t translated_path_length = data_val.dsize - 1; - - DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); - DO_PROFILE_INC(statcache_hits); - if(SMB_VFS_STAT(conn,translated_path, pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - tdb_delete_bystring(tdb_stat_cache, chk_name); - SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); - return False; - } - - if (!sizechanged) { - memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length)); - } else if (num_components == 0) { - pstrcpy(name, translated_path); - } else { - sp = strnrchr_m(name, '/', num_components); - if (sp) { - pstring last_component; - pstrcpy(last_component, sp); - pstrcpy(name, translated_path); - pstrcat(name, last_component); - } else { - pstrcpy(name, translated_path); - } - } - - /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[translated_path_length]; - if(**start == '/') - ++*start; - - pstrcpy(dirpath, translated_path); - retval = (namelen == translated_path_length) ? True : False; + DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); + return False; + } + + *sp = '\0'; + + /* + * Count the number of times we have done this, we'll + * need it when reconstructing the string. + */ + if (sizechanged) + num_components++; + + if ((*chk_name == '\0') + || ISDOT(chk_name) || ISDOTDOT(chk_name)) { + DO_PROFILE_INC(statcache_misses); SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); - return retval; + return False; + } + } + + translated_path = (char *)data_val.dptr; + translated_path_length = data_val.dsize - 1; + + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " + "-> [%s]\n", chk_name, translated_path )); + DO_PROFILE_INC(statcache_hits); + + if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + tdb_delete_bystring(tdb_stat_cache, chk_name); + SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); + return False; + } + + if (!sizechanged) { + memcpy(name, translated_path, + MIN(sizeof(pstring)-1, translated_path_length)); + } else if (num_components == 0) { + pstrcpy(name, translated_path); + } else { + char *sp; + + sp = strnrchr_m(name, '/', num_components); + if (sp) { + pstring last_component; + pstrcpy(last_component, sp); + pstrcpy(name, translated_path); + pstrcat(name, last_component); + } else { + pstrcpy(name, translated_path); } } + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[translated_path_length]; + if (**start == '/') + ++*start; + + pstrcpy(dirpath, translated_path); + SAFE_FREE(chk_name); + SAFE_FREE(data_val.dptr); + return (namelen == translated_path_length); } /*************************************************************************** -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 92c845ce2e..17fda8163d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/statcache.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 17fda8163d..51e8c0417a 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -16,8 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From f01698027d15ca546d9a92c799d0cad18a625789 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 22:39:11 +0000 Subject: r23844: Add patch series from Volker (after review and consultation). 0001-Save-a-strdup-in-stat_cache_add.patch 0002-Use-ISDOT-and-ISDOTDOT.patch 0003-Move-fname_equal-around.patch 0004-unix_convert-pstring-dirpath-char.patch 0005-Ignore-.o-files.patch 0006-Get-rid-of-pstrings-inside-unix_convert.patch 0007-revert-pstring-unix_convert.patch 0008-Make-name-an-allocated-pstring-inside-unix_convert.patch 0009-Pass-explicit-pstring-to-mangle_check_cache.patch 0010-Don-t-overwrite-orig_path-unnecessarily.patch 0011-Defer-allocating-name.patch 0012-Make-sure-dirpath-is-always-correctly-allocated.patch 0013-Remove-one-pstring-dependency-in-unix_convert.patch 0014-Remove-more-name-pstring-dependencies.patch 0015-Hide-the-nasty-API-of-mangle_check_cache-in-mangle_c.patch 0016-name-does-not-need-to-be-pstring-size-anymore.patch 0017-Make-use-of-ISDOT-and-ISDOTDOT.patch 0018-Remove-pstring-from-stat_cache_lookup.patch 0019-Add-my-copyright.patch To remove pstrings from statcache and unix_convert. Jeremy. (This used to be commit ea6ef368891af24164d2e76700c405a82b3dfc19) --- source3/smbd/statcache.c | 84 +++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 33 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 51e8c0417a..24cfe3beb8 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 + Copyright (C) Volker Lendecke 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,9 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) +void stat_cache_add( const char *full_orig_name, const char *translated_path, BOOL case_sensitive) { - char *translated_path; size_t translated_path_length; TDB_DATA data_val; char *original_path; @@ -61,10 +61,10 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * Don't cache trivial valid directory entries such as . and .. */ - if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && - ((full_orig_name[1] == '\0') || - (full_orig_name[1] == '.' && full_orig_name[2] == '\0')))) + if ((*full_orig_name == '\0') + || ISDOT(full_orig_name) || ISDOTDOT(full_orig_name)) { return; + } /* * If we are in case insentive mode, we don't need to @@ -72,7 +72,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * would be a waste. */ - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) return; /* @@ -80,14 +80,15 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * translated path. */ - translated_path = SMB_STRDUP(orig_translated_path); - if (!translated_path) - return; + /* + * To save a strdup we don't necessarily 0-terminate the translated + * path in the tdb. Instead, we do it directly after the tdb_fetch in + * stat_cache_lookup. + */ translated_path_length = strlen(translated_path); if(translated_path[translated_path_length-1] == '/') { - translated_path[translated_path_length-1] = '\0'; translated_path_length--; } @@ -98,7 +99,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } if (!original_path) { - SAFE_FREE(translated_path); return; } @@ -114,7 +114,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); SAFE_FREE(original_path); - SAFE_FREE(translated_path); return; } @@ -140,7 +139,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } SAFE_FREE(original_path); - SAFE_FREE(translated_path); } /** @@ -148,7 +146,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine - * to be correct as far as the cache can tell us + * to be correct as far as the cache can tell us. We assume that + * it is a malloc'ed string, we free it if necessary. * @param dirpath The path as far as the stat cache told us. * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. @@ -157,7 +156,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat * */ -BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, +BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, char **start, SMB_STRUCT_STAT *pst) { char *chk_name; @@ -167,10 +166,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char *translated_path; size_t translated_path_length; TDB_DATA data_val; + char *name; if (!lp_stat_cache()) return False; + name = *pname; namelen = strlen(name); *start = name; @@ -180,10 +181,9 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, /* * Don't lookup trivial valid directory entries. */ - if((*name == '\0') || (name[0] == '.' && - ((name[1] == '\0') || - (name[1] == '.' && name[1] == '\0')))) + if ((*name == '\0') || ISDOT(name) || ISDOTDOT(name)) { return False; + } if (conn->case_sensitive) { chk_name = SMB_STRDUP(name); @@ -250,6 +250,12 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, translated_path = (char *)data_val.dptr; translated_path_length = data_val.dsize - 1; + /* + * In stat_cache_add we did not necessarily 0-terminate the translated + * path. Do it here, where we do have a freshly malloc'ed blob. + */ + translated_path[translated_path_length] = '\0'; + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); @@ -264,31 +270,43 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if (!sizechanged) { memcpy(name, translated_path, - MIN(sizeof(pstring)-1, translated_path_length)); - } else if (num_components == 0) { - pstrcpy(name, translated_path); - } else { - char *sp; - - sp = strnrchr_m(name, '/', num_components); - if (sp) { - pstring last_component; - pstrcpy(last_component, sp); - pstrcpy(name, translated_path); - pstrcat(name, last_component); + MIN(namelen, translated_path_length)); + } + else { + if (num_components == 0) { + name = SMB_STRNDUP(translated_path, + translated_path_length); } else { - pstrcpy(name, translated_path); + char *sp; + + sp = strnrchr_m(name, '/', num_components); + if (sp) { + asprintf(&name, "%.*s%s", + (int)translated_path_length, + translated_path, sp); + } else { + name = SMB_STRNDUP(translated_path, + translated_path_length); + } } + if (name == NULL) { + /* + * TODO: Get us out of here with a real error message + */ + smb_panic("malloc failed"); + } + SAFE_FREE(*pname); + *pname = name; } + /* set pointer for 'where to start' on fixing the rest of the name */ *start = &name[translated_path_length]; if (**start == '/') ++*start; - pstrcpy(dirpath, translated_path); + *dirpath = translated_path; SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); return (namelen == translated_path_length); } -- cgit From dacdde6e5c047ad9a0e416dcff7afdc5e21fc4ce Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 30 Aug 2007 23:07:10 +0000 Subject: r24813: Reformat to 80 columns. Jeremy. (This used to be commit c6c8f5a897602d53876fe75e86283d97a394037d) --- source3/smbd/statcache.c | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 24cfe3beb8..d2f09930a0 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -1,21 +1,21 @@ -/* +/* Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1999-2004 Copyright (C) Andrew Bartlett 2003 Copyright (C) Volker Lendecke 2007 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ @@ -33,14 +33,15 @@ static TDB_CONTEXT *tdb_stat_cache; * * @param full_orig_name The original name as specified by the client * @param orig_translated_path The name on our filesystem. - * - * @note Only the first strlen(orig_translated_path) characters are stored + * + * @note Only the first strlen(orig_translated_path) characters are stored * into the cache. This means that full_orig_name will be internally * truncated. * */ -void stat_cache_add( const char *full_orig_name, const char *translated_path, BOOL case_sensitive) +void stat_cache_add( const char *full_orig_name, const char *translated_path, + BOOL case_sensitive) { size_t translated_path_length; TDB_DATA data_val; @@ -111,8 +112,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", - original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); + DEBUG(0, ("OOPS - tried to store stat cache entry " + "for weird length paths [%s] %lu and [%s] %lu)!\n", + original_path, + (unsigned long)original_path_length, + translated_path, + (unsigned long)translated_path_length)); SAFE_FREE(original_path); return; } @@ -127,15 +132,20 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO /* * New entry or replace old entry. */ - + data_val.dsize = translated_path_length + 1; data_val.dptr = (uint8 *)translated_path; - if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { - DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, + TDB_REPLACE) != 0) { + DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", + original_path, translated_path)); } else { DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", - (unsigned long)data_val.dptr, (unsigned int)data_val.dsize, original_path, translated_path)); + (unsigned long)data_val.dptr, + (unsigned int)data_val.dsize, + original_path, + translated_path)); } SAFE_FREE(original_path); @@ -149,10 +159,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, BO * to be correct as far as the cache can tell us. We assume that * it is a malloc'ed string, we free it if necessary. * @param dirpath The path as far as the stat cache told us. - * @param start A pointer into name, for where to 'start' in fixing the rest of the name up. + * @param start A pointer into name, for where to 'start' in fixing the rest + * of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. * - * @return True if we translated (and did a scuccessful stat on) the entire name. + * @return True if we translated (and did a scuccessful stat on) the entire + * name. * */ @@ -170,7 +182,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, if (!lp_stat_cache()) return False; - + name = *pname; namelen = strlen(name); @@ -217,7 +229,8 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, break; } - DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", + chk_name )); /* * Didn't find it - remove last component for next try. */ @@ -348,7 +361,7 @@ void stat_cache_delete(const char *name) The function returns the bucket index number for the hashed key. JRA. Use a djb-algorithm hash for speed. ***************************************************************/ - + unsigned int fast_string_hash(TDB_DATA *key) { unsigned int n = 0; @@ -374,7 +387,7 @@ BOOL reset_stat_cache( void ) /* Create the in-memory tdb using our custom hash function. */ tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); + (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); if (!tdb_stat_cache) return False; -- cgit From 132ee3990af5d31573978f5a3abf43db2303880b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 20:57:01 +0000 Subject: r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736) --- source3/smbd/statcache.c | 128 ++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 57 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index d2f09930a0..a066091b52 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. stat cache code Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Jeremy Allison 1999-2004 + Copyright (C) Jeremy Allison 1999-2007 Copyright (C) Andrew Bartlett 2003 Copyright (C) Volker Lendecke 2007 @@ -40,7 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache; * */ -void stat_cache_add( const char *full_orig_name, const char *translated_path, +void stat_cache_add( const char *full_orig_name, + char *translated_path, BOOL case_sensitive) { size_t translated_path_length; @@ -48,9 +49,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, char *original_path; size_t original_path_length; size_t sc_size = lp_max_stat_cache_size(); + char saved_char; + TALLOC_CTX *ctx = talloc_tos(); - if (!lp_stat_cache()) + if (!lp_stat_cache()) { return; + } if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { reset_stat_cache(); @@ -73,20 +77,15 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * would be a waste. */ - if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) + if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) { return; + } /* * Remove any trailing '/' characters from the * translated path. */ - /* - * To save a strdup we don't necessarily 0-terminate the translated - * path in the tdb. Instead, we do it directly after the tdb_fetch in - * stat_cache_lookup. - */ - translated_path_length = strlen(translated_path); if(translated_path[translated_path_length-1] == '/') { @@ -94,9 +93,9 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, } if(case_sensitive) { - original_path = SMB_STRDUP(full_orig_name); + original_path = talloc_strdup(ctx,full_orig_name); } else { - original_path = strdup_upper(full_orig_name); + original_path = talloc_strdup_upper(ctx,full_orig_name); } if (!original_path) { @@ -118,7 +117,7 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); - SAFE_FREE(original_path); + TALLOC_FREE(original_path); return; } @@ -129,13 +128,17 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, original_path_length = translated_path_length; } - /* - * New entry or replace old entry. - */ + /* Ensure we're null terminated. */ + saved_char = translated_path[translated_path_length]; + translated_path[translated_path_length] = '\0'; data_val.dsize = translated_path_length + 1; data_val.dptr = (uint8 *)translated_path; + /* + * New entry or replace old entry. + */ + if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", @@ -148,7 +151,8 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, translated_path)); } - SAFE_FREE(original_path); + translated_path[translated_path_length] = saved_char; + TALLOC_FREE(original_path); } /** @@ -157,8 +161,10 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * @param conn A connection struct to do the stat() with. * @param name The path we are attempting to cache, modified by this routine * to be correct as far as the cache can tell us. We assume that - * it is a malloc'ed string, we free it if necessary. - * @param dirpath The path as far as the stat cache told us. + * it is a talloc'ed string from top of stack, we free it if + * necessary. + * @param dirpath The path as far as the stat cache told us. Also talloced + * from top of stack. * @param start A pointer into name, for where to 'start' in fixing the rest * of the name up. * @param psd A stat buffer, NOT from the cache, but just a side-effect. @@ -168,8 +174,11 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path, * */ -BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, - char **start, SMB_STRUCT_STAT *pst) +BOOL stat_cache_lookup(connection_struct *conn, + char **pp_name, + char **pp_dirpath, + char **pp_start, + SMB_STRUCT_STAT *pst) { char *chk_name; size_t namelen; @@ -179,15 +188,18 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, size_t translated_path_length; TDB_DATA data_val; char *name; + TALLOC_CTX *ctx = talloc_tos(); - if (!lp_stat_cache()) + *pp_dirpath = NULL; + *pp_start = *pp_name; + + if (!lp_stat_cache()) { return False; + } - name = *pname; + name = *pp_name; namelen = strlen(name); - *start = name; - DO_PROFILE_INC(statcache_lookups); /* @@ -198,14 +210,14 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, } if (conn->case_sensitive) { - chk_name = SMB_STRDUP(name); + chk_name = talloc_strdup(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); return False; } } else { - chk_name = strdup_upper(name); + chk_name = talloc_strdup_upper(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); return False; @@ -216,8 +228,9 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * if we uppercase. We need to treat this differently * below. */ - if (strlen(chk_name) != namelen) + if (strlen(chk_name) != namelen) { sizechanged = True; + } } while (1) { @@ -239,7 +252,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); + TALLOC_FREE(chk_name); return False; } @@ -249,25 +262,25 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, * Count the number of times we have done this, we'll * need it when reconstructing the string. */ - if (sizechanged) + + if (sizechanged) { num_components++; + } if ((*chk_name == '\0') || ISDOT(chk_name) || ISDOTDOT(chk_name)) { DO_PROFILE_INC(statcache_misses); - SAFE_FREE(chk_name); + TALLOC_FREE(chk_name); return False; } } - translated_path = (char *)data_val.dptr; + translated_path = talloc_strdup(ctx,(char *)data_val.dptr); + if (!translated_path) { + smb_panic("talloc failed"); + } translated_path_length = data_val.dsize - 1; - - /* - * In stat_cache_add we did not necessarily 0-terminate the translated - * path. Do it here, where we do have a freshly malloc'ed blob. - */ - translated_path[translated_path_length] = '\0'; + SAFE_FREE(data_val.dptr); DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); @@ -276,50 +289,51 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath, if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ tdb_delete_bystring(tdb_stat_cache, chk_name); - SAFE_FREE(chk_name); - SAFE_FREE(data_val.dptr); + TALLOC_FREE(chk_name); + TALLOC_FREE(translated_path); return False; } if (!sizechanged) { - memcpy(name, translated_path, + memcpy(*pp_name, translated_path, MIN(namelen, translated_path_length)); - } - else { + } else { if (num_components == 0) { - name = SMB_STRNDUP(translated_path, + name = talloc_strndup(ctx, translated_path, translated_path_length); } else { char *sp; sp = strnrchr_m(name, '/', num_components); if (sp) { - asprintf(&name, "%.*s%s", + name = talloc_asprintf(ctx,"%.*s%s", (int)translated_path_length, translated_path, sp); } else { - name = SMB_STRNDUP(translated_path, - translated_path_length); + name = talloc_strndup(ctx, + translated_path, + translated_path_length); } } if (name == NULL) { /* * TODO: Get us out of here with a real error message */ - smb_panic("malloc failed"); + smb_panic("talloc failed"); } - SAFE_FREE(*pname); - *pname = name; + TALLOC_FREE(*pp_name); + *pp_name = name; } /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[translated_path_length]; - if (**start == '/') - ++*start; + *pp_start = &name[translated_path_length]; + if (**pp_start == '/') { + ++*pp_start; + } - *dirpath = translated_path; - SAFE_FREE(chk_name); + *pp_dirpath = translated_path; + TALLOC_FREE(chk_name); return (namelen == translated_path_length); } @@ -344,7 +358,7 @@ void send_stat_cache_delete_message(const char *name) void stat_cache_delete(const char *name) { - char *lname = strdup_upper(name); + char *lname = talloc_strdup_upper(talloc_tos(), name); if (!lname) { return; @@ -353,7 +367,7 @@ void stat_cache_delete(const char *name) lname, name )); tdb_delete_bystring(tdb_stat_cache, lname); - SAFE_FREE(lname); + TALLOC_FREE(lname); } /*************************************************************** -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/statcache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index a066091b52..8f1e008985 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -42,7 +42,7 @@ static TDB_CONTEXT *tdb_stat_cache; void stat_cache_add( const char *full_orig_name, char *translated_path, - BOOL case_sensitive) + bool case_sensitive) { size_t translated_path_length; TDB_DATA data_val; @@ -174,7 +174,7 @@ void stat_cache_add( const char *full_orig_name, * */ -BOOL stat_cache_lookup(connection_struct *conn, +bool stat_cache_lookup(connection_struct *conn, char **pp_name, char **pp_dirpath, char **pp_start, @@ -182,7 +182,7 @@ BOOL stat_cache_lookup(connection_struct *conn, { char *chk_name; size_t namelen; - BOOL sizechanged = False; + bool sizechanged = False; unsigned int num_components = 0; char *translated_path; size_t translated_path_length; @@ -390,7 +390,7 @@ unsigned int fast_string_hash(TDB_DATA *key) Initializes or clears the stat cache. **************************************************************************/ -BOOL reset_stat_cache( void ) +bool reset_stat_cache( void ) { if (!lp_stat_cache()) return True; -- cgit From f427d4ce65659419c8989d87acd97d00b4db41e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 18 Dec 2007 09:41:03 +0100 Subject: Add a in-memory cache This is a more general API that caches data with a LRU scheme. See include/cache.h. No comments yet, I'm still working on it. But Jeremy has given me a hint in one of his checkins that he would like to make use of this now. The idea is that we get rid of all our silly little caches and merge them all into one cache that we can then very easily trim, for example even with a smbcontrol message if someone decides memory is tight. The main user is the stat cache, this patch also converts the getwd cache. More caches to come. (This used to be commit 7a911b35713538d82001a3c9f34152e293fe1943) --- source3/smbd/statcache.c | 64 +++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) (limited to 'source3/smbd/statcache.c') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 8f1e008985..72fed008a2 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -26,8 +26,6 @@ Stat cache code used in unix_convert. *****************************************************************************/ -static TDB_CONTEXT *tdb_stat_cache; - /** * Add an entry into the stat cache. * @@ -45,10 +43,8 @@ void stat_cache_add( const char *full_orig_name, bool case_sensitive) { size_t translated_path_length; - TDB_DATA data_val; char *original_path; size_t original_path_length; - size_t sc_size = lp_max_stat_cache_size(); char saved_char; TALLOC_CTX *ctx = talloc_tos(); @@ -56,12 +52,6 @@ void stat_cache_add( const char *full_orig_name, return; } - if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { - reset_stat_cache(); - } - - ZERO_STRUCT(data_val); - /* * Don't cache trivial valid directory entries such as . and .. */ @@ -132,24 +122,20 @@ void stat_cache_add( const char *full_orig_name, saved_char = translated_path[translated_path_length]; translated_path[translated_path_length] = '\0'; - data_val.dsize = translated_path_length + 1; - data_val.dptr = (uint8 *)translated_path; - /* * New entry or replace old entry. */ - if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, - TDB_REPLACE) != 0) { - DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", - original_path, translated_path)); - } else { - DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", - (unsigned long)data_val.dptr, - (unsigned int)data_val.dsize, - original_path, - translated_path)); - } + memcache_add( + smbd_memcache(), STAT_CACHE, + data_blob_const(original_path, original_path_length), + data_blob_const(translated_path, translated_path_length + 1)); + + DEBUG(5,("stat_cache_add: Added entry (%lx:size %x) %s -> %s\n", + (unsigned long)translated_path, + (unsigned int)translated_path_length, + original_path, + translated_path)); translated_path[translated_path_length] = saved_char; TALLOC_FREE(original_path); @@ -186,7 +172,7 @@ bool stat_cache_lookup(connection_struct *conn, unsigned int num_components = 0; char *translated_path; size_t translated_path_length; - TDB_DATA data_val; + DATA_BLOB data_val; char *name; TALLOC_CTX *ctx = talloc_tos(); @@ -236,9 +222,12 @@ bool stat_cache_lookup(connection_struct *conn, while (1) { char *sp; - data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); + data_val = data_blob_null; - if (data_val.dptr != NULL && data_val.dsize != 0) { + if (memcache_lookup( + smbd_memcache(), STAT_CACHE, + data_blob_const(chk_name, strlen(chk_name)), + &data_val)) { break; } @@ -275,12 +264,11 @@ bool stat_cache_lookup(connection_struct *conn, } } - translated_path = talloc_strdup(ctx,(char *)data_val.dptr); + translated_path = talloc_strdup(ctx,(char *)data_val.data); if (!translated_path) { smb_panic("talloc failed"); } - translated_path_length = data_val.dsize - 1; - SAFE_FREE(data_val.dptr); + translated_path_length = data_val.length - 1; DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); @@ -288,7 +276,8 @@ bool stat_cache_lookup(connection_struct *conn, if (SMB_VFS_STAT(conn, translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ - tdb_delete_bystring(tdb_stat_cache, chk_name); + memcache_delete(smbd_memcache(), STAT_CACHE, + data_blob_const(chk_name, strlen(chk_name))); TALLOC_FREE(chk_name); TALLOC_FREE(translated_path); return False; @@ -366,7 +355,8 @@ void stat_cache_delete(const char *name) DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n", lname, name )); - tdb_delete_bystring(tdb_stat_cache, lname); + memcache_delete(smbd_memcache(), STAT_CACHE, + data_blob_const(lname, talloc_get_size(lname)-1)); TALLOC_FREE(lname); } @@ -395,15 +385,7 @@ bool reset_stat_cache( void ) if (!lp_stat_cache()) return True; - if (tdb_stat_cache) { - tdb_close(tdb_stat_cache); - } + memcache_flush(smbd_memcache(), STAT_CACHE); - /* Create the in-memory tdb using our custom hash function. */ - tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, - (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); - - if (!tdb_stat_cache) - return False; return True; } -- cgit