diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/mangle_hash2.c | 67 | ||||
-rw-r--r-- | source3/smbd/server.c | 13 | ||||
-rw-r--r-- | source3/smbd/statcache.c | 64 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 168 |
4 files changed, 112 insertions, 200 deletions
diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 7066c2a4e5..9643506aea 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -93,15 +93,6 @@ static unsigned char char_flags[256]; */ static unsigned mangle_prefix; -/* we will use a very simple direct mapped prefix cache. The big - advantage of this cache structure is speed and low memory usage - - The cache is indexed by the low-order bits of the hash, and confirmed by - hashing the resulting cache entry to match the known hash -*/ -static char **prefix_cache; -static unsigned int *prefix_cache_hashes; - /* these are the characters we use in the 8.3 hash. Must be 36 chars long */ static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static unsigned char base_reverse[256]; @@ -147,57 +138,39 @@ static unsigned int mangle_hash(const char *key, unsigned int length) return value & ~0x80000000; } -/* - initialise (ie. allocate) the prefix cache - */ -static bool cache_init(void) -{ - if (prefix_cache) { - return True; - } - - prefix_cache = SMB_CALLOC_ARRAY(char *,MANGLE_CACHE_SIZE); - if (!prefix_cache) { - return False; - } - - prefix_cache_hashes = SMB_CALLOC_ARRAY(unsigned int, MANGLE_CACHE_SIZE); - if (!prefix_cache_hashes) { - SAFE_FREE(prefix_cache); - return False; - } - - return True; -} - /* insert an entry into the prefix cache. The string might not be null terminated */ static void cache_insert(const char *prefix, int length, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + char *str = SMB_STRNDUP(prefix, length); - if (prefix_cache[i]) { - free(prefix_cache[i]); + if (str == NULL) { + return; } - prefix_cache[i] = SMB_STRNDUP(prefix, length); - prefix_cache_hashes[i] = hash; + memcache_add(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), + data_blob_const(str, length+1)); + SAFE_FREE(str); } /* lookup an entry in the prefix cache. Return NULL if not found. */ -static const char *cache_lookup(unsigned int hash) +static char *cache_lookup(TALLOC_CTX *mem_ctx, unsigned int hash) { - int i = hash % MANGLE_CACHE_SIZE; + DATA_BLOB value; - if (!prefix_cache[i] || hash != prefix_cache_hashes[i]) { + if (!memcache_lookup(smbd_memcache(), MANGLE_HASH2_CACHE, + data_blob_const(&hash, sizeof(hash)), &value)) { return NULL; } - /* yep, it matched */ - return prefix_cache[i]; + SMB_ASSERT((value.length > 0) + && (value.data[value.length-1] == '\0')); + + return talloc_strdup(mem_ctx, (char *)value.data); } @@ -377,7 +350,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, { unsigned int hash, multiplier; unsigned int i; - const char *prefix; + char *prefix; char extension[4]; *pp_out = NULL; @@ -397,7 +370,7 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, } /* now look in the prefix cache for that hash */ - prefix = cache_lookup(hash); + prefix = cache_lookup(ctx, hash); if (!prefix) { M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n", name, hash)); @@ -421,6 +394,8 @@ static bool lookup_name_from_8_3(TALLOC_CTX *ctx, *pp_out = talloc_strdup(ctx, prefix); } + TALLOC_FREE(prefix); + if (!pp_out) { M_DEBUG(0,("talloc_fail")); return False; @@ -728,10 +703,6 @@ struct mangle_fns *mangle_hash2_init(void) init_tables(); mangle_reset(); - if (!cache_init()) { - return NULL; - } - return &mangle_fns; } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 41d036a8b9..574197d711 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -86,6 +86,19 @@ struct messaging_context *smbd_messaging_context(void) return ctx; } +struct memcache *smbd_memcache(void) +{ + static struct memcache *cache; + + if (!cache + && !(cache = memcache_init(NULL, + lp_max_stat_cache_size()*1024))) { + + smb_panic("Could not init smbd memcache"); + } + return cache; +} + /******************************************************************* What to do when smb.conf is updated. ********************************************************************/ 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; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 628d2eec4b..45d0788117 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -731,152 +731,98 @@ int vfs_ChDir(connection_struct *conn, const char *path) return(res); } -/* number of list structures for a caching GetWd function. */ -#define MAX_GETWDCACHE (50) - -static struct { - SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */ - SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */ - char *path; /* The pathname. */ - bool valid; -} ino_list[MAX_GETWDCACHE]; - -extern bool use_getwd_cache; - -/**************************************************************************** - Prompte a ptr (to make it recently used) -****************************************************************************/ - -static void array_promote(char *array,int elsize,int element) -{ - char *p; - if (element == 0) - return; - - p = (char *)SMB_MALLOC(elsize); - - if (!p) { - DEBUG(5,("array_promote: malloc fail\n")); - return; - } - - memcpy(p,array + element * elsize, elsize); - memmove(array + elsize,array,elsize*element); - memcpy(array,p,elsize); - SAFE_FREE(p); -} - /******************************************************************* Return the absolute current directory path - given a UNIX pathname. Note that this path is returned in DOS format, not UNIX format. Note this can be called with conn == NULL. ********************************************************************/ +struct getwd_cache_key { + SMB_DEV_T dev; + SMB_INO_T ino; +}; + char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) { char s[PATH_MAX+1]; - static bool getwd_cache_init = False; SMB_STRUCT_STAT st, st2; - int i; - char *ret = NULL; + char *result; + DATA_BLOB cache_value; + struct getwd_cache_key key; *s = 0; - if (!use_getwd_cache) { - nocache: - ret = SMB_VFS_GETWD(conn,s); - if (!ret) { - DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, " - "errno %s\n",strerror(errno))); - return NULL; - } - return talloc_strdup(ctx, ret); - } - - /* init the cache */ - if (!getwd_cache_init) { - getwd_cache_init = True; - for (i=0;i<MAX_GETWDCACHE;i++) { - string_set(&ino_list[i].path,""); - ino_list[i].valid = False; - } + if (!lp_getwd_cache()) { + goto nocache; } - /* Get the inode of the current directory, if this doesn't work we're - in trouble :-) */ + SET_STAT_INVALID(st); if (SMB_VFS_STAT(conn, ".",&st) == -1) { - /* Known to fail for root: the directory may be - * NFS-mounted and exported with root_squash (so has no root access). */ + /* + * Known to fail for root: the directory may be NFS-mounted + * and exported with root_squash (so has no root access). + */ DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s " - "(NFS problem ?)\n", - strerror(errno) )); + "(NFS problem ?)\n", strerror(errno) )); goto nocache; } + ZERO_STRUCT(key); /* unlikely, but possible padding */ + key.dev = st.st_dev; + key.ino = st.st_ino; - for (i=0; i<MAX_GETWDCACHE; i++) { - if (ino_list[i].valid) { - - /* If we have found an entry with a matching inode and dev number - then find the inode number for the directory in the cached string. - If this agrees with that returned by the stat for the current - directory then all is o.k. (but make sure it is a directory all - the same...) */ - - if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) { - if (SMB_VFS_STAT(conn,ino_list[i].path,&st2) == 0) { - if (st.st_ino == st2.st_ino && st.st_dev == st2.st_dev && - (st2.st_mode & S_IFMT) == S_IFDIR) { + if (!memcache_lookup(smbd_memcache(), GETWD_CACHE, + data_blob_const(&key, sizeof(key)), + &cache_value)) { + goto nocache; + } - ret = talloc_strdup(ctx, - ino_list[i].path); + SMB_ASSERT((cache_value.length > 0) + && (cache_value.data[cache_value.length-1] == '\0')); - /* promote it for future use */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); - if (ret == NULL) { - errno = ENOMEM; - } - return ret; - } else { - /* If the inode is different then something's changed, - scrub the entry and start from scratch. */ - ino_list[i].valid = False; - } - } - } + if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0) + && (st.st_dev == st2.st_dev) && (st.st_ino == st2.st_ino) + && (S_ISDIR(st.st_mode))) { + /* + * Ok, we're done + */ + result = talloc_strdup(ctx, (char *)cache_value.data); + if (result == NULL) { + errno = ENOMEM; } + return result; } - /* We don't have the information to hand so rely on traditional - * methods. The very slow getcwd, which spawns a process on some - * systems, or the not quite so bad getwd. */ + nocache: + + /* + * We don't have the information to hand so rely on traditional + * methods. The very slow getcwd, which spawns a process on some + * systems, or the not quite so bad getwd. + */ if (!SMB_VFS_GETWD(conn,s)) { - DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n", - strerror(errno))); - return (NULL); + DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n", + strerror(errno))); + return NULL; } - ret = talloc_strdup(ctx,s); - - DEBUG(5,("vfs_GetWd %s, inode %.0f, dev %.0f\n", - s,(double)st.st_ino,(double)st.st_dev)); - - /* add it to the cache */ - i = MAX_GETWDCACHE - 1; - string_set(&ino_list[i].path,s); - ino_list[i].dev = st.st_dev; - ino_list[i].inode = st.st_ino; - ino_list[i].valid = True; + if (lp_getwd_cache() && VALID_STAT(st)) { + ZERO_STRUCT(key); /* unlikely, but possible padding */ + key.dev = st.st_dev; + key.ino = st.st_ino; - /* put it at the top of the list */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); + memcache_add(smbd_memcache(), GETWD_CACHE, + data_blob_const(&key, sizeof(key)), + data_blob_const(s, strlen(s)+1)); + } - if (ret == NULL) { + result = talloc_strdup(ctx, s); + if (result == NULL) { errno = ENOMEM; } - return ret; + return result; } /******************************************************************* |