From 92bb16f2fcd3a2288222d6db37ff0ce5f4b05eb0 Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Fri, 11 Nov 2011 10:15:02 +0100 Subject: [PATCH] Enhance mountcache with rescan option after interval. The mountcache shouldn't be a static cache that lives forever in the filed. Mountpoint come and go on modern systems so on a failure to lookup a mountpoint in the cache we trigger a rescan. We also rescan the cache on lookup when more the 30 minutes have past since the last rescan of the data. This way we should have less stale data. Having old data is not so much a problem but missing new data is this new rules should make this cache somewhat robust. --- bacula/src/lib/mntent_cache.c | 50 ++++++++++++++++++++++++++++++----- bacula/src/lib/mntent_cache.h | 8 ++++-- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/bacula/src/lib/mntent_cache.c b/bacula/src/lib/mntent_cache.c index 7db4475986..2c68bdcefc 100644 --- a/bacula/src/lib/mntent_cache.c +++ b/bacula/src/lib/mntent_cache.c @@ -99,12 +99,17 @@ static pthread_mutex_t mntent_cache_lock = PTHREAD_MUTEX_INITIALIZER; static mntent_cache_entry_t *previous_cache_hit = NULL; static htable *mntent_cache_entry_hashtable = NULL; +/* + * Last time a rescan of the mountlist took place. + */ +static time_t last_rescan = 0; + /** * Add a new entry to the cache. * This function should be called with a write lock on the mntent_cache. */ -static void add_mntent_mapping(uint32_t dev, const char *special, const char *mountpoint, - const char *fstype, const char *mntopts) +static inline void add_mntent_mapping(uint32_t dev, const char *special, const char *mountpoint, + const char *fstype, const char *mntopts) { int len; mntent_cache_entry_t *mce; @@ -364,11 +369,6 @@ static void initialize_mntent_cache(void) V(mntent_cache_lock); } -void preload_mntent_cache(void) -{ - initialize_mntent_cache(); -} - void flush_mntent_cache(void) { /** @@ -393,12 +393,25 @@ void flush_mntent_cache(void) mntent_cache_entry_t *find_mntent_mapping(uint32_t dev) { mntent_cache_entry_t *mce = NULL; + time_t now; /** * Initialize the cache if that was not done before. */ if (!mntent_cache_entry_hashtable) { initialize_mntent_cache(); + last_rescan = time(NULL); + } else { + /** + * We rescan the mountlist when called when more then + * MNTENT_RESCAN_INTERVAL seconds have past since the + * last rescan. This way we never work with data older + * then MNTENT_RESCAN_INTERVAL seconds. + */ + now = time(NULL); + if ((now - last_rescan) > MNTENT_RESCAN_INTERVAL) { + initialize_mntent_cache(); + } } /** @@ -414,6 +427,29 @@ mntent_cache_entry_t *find_mntent_mapping(uint32_t dev) P(mntent_cache_lock); mce = (mntent_cache_entry_t *)mntent_cache_entry_hashtable->lookup(dev); + + /** + * If we fail to lookup the mountpoint its probably a mountpoint added + * after we did our initial scan. Lets rescan the mountlist and try + * the lookup again. + */ + if (!mce) { + /** + * Make sure the cache is empty (either by flushing it or by initializing it.) + */ + clear_mount_cache(); + + /** + * Refresh the cache. + */ + refresh_mount_cache(); + + mce = (mntent_cache_entry_t *)mntent_cache_entry_hashtable->lookup(dev); + } + + /* + * Store the last successfull lookup as the previous_cache_hit. + */ if (mce) { previous_cache_hit = mce; } diff --git a/bacula/src/lib/mntent_cache.h b/bacula/src/lib/mntent_cache.h index 36bd5243e0..82c2f64f1f 100644 --- a/bacula/src/lib/mntent_cache.h +++ b/bacula/src/lib/mntent_cache.h @@ -33,6 +33,12 @@ #ifndef _MNTENT_CACHE_H #define _MNTENT_CACHE_H 1 +/* + * Don't use the mountlist data when its older then this amount + * of seconds but perform a rescan of the mountlist. + */ +#define MNTENT_RESCAN_INTERVAL 1800 + /* * Initial size of number of hash entries we expect in the cache. * If more are needed the hash table will grow as needed. @@ -54,8 +60,6 @@ struct mntent_cache_entry_t { }; mntent_cache_entry_t *find_mntent_mapping(uint32_t dev); - -void preload_mntent_cache(void); void flush_mntent_cache(void); #endif /* _MNTENT_CACHE_H */ -- 2.39.5