X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fmntent_cache.c;h=aa46efa2a79317e7b6ba85b17bbb06362c446c60;hb=3e94dc8ebc677d8b7a42952a95d99e9793537d28;hp=14422c040356a842770a518d62fb564e17a43895;hpb=98a43b9a3001a892e6b28accabf1f88c3bbae913;p=bacula%2Fbacula diff --git a/bacula/src/lib/mntent_cache.c b/bacula/src/lib/mntent_cache.c index 14422c0403..aa46efa2a7 100644 --- a/bacula/src/lib/mntent_cache.c +++ b/bacula/src/lib/mntent_cache.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2009-2010 Free Software Foundation Europe e.V. + Copyright (C) 2009-2011 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -99,12 +99,20 @@ 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; @@ -340,14 +348,10 @@ static void clear_mount_cache() /** * Initialize the cache for use. + * This function should be called with a write lock on the mntent_cache. */ static void initialize_mntent_cache(void) { - /** - * Lock the cache while we update it. - */ - P(mntent_cache_lock); - /** * Make sure the cache is empty (either by flushing it or by initializing it.) */ @@ -357,33 +361,24 @@ static void initialize_mntent_cache(void) * Refresh the cache. */ refresh_mount_cache(); - - /** - * We are done updating the cache. - */ - V(mntent_cache_lock); -} - -void preload_mntent_cache(void) -{ - initialize_mntent_cache(); } +/** + * Flush the current content from the cache. + */ void flush_mntent_cache(void) { /** - * Lock the cache while we update it. + * Lock the cache. */ P(mntent_cache_lock); - /** - * Make sure the cache is empty (either by flushing it or by initializing it.) - */ - clear_mount_cache(); + if (mntent_cache_entry_hashtable) { + previous_cache_hit = NULL; + mntent_cache_entry_hashtable->destroy(); + mntent_cache_entry_hashtable = NULL; + } - /** - * We are done updating the cache. - */ V(mntent_cache_lock); } @@ -393,34 +388,60 @@ 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. + * Lock the cache. */ - if (!mntent_cache_entry_hashtable) { - initialize_mntent_cache(); - } + P(mntent_cache_lock); /** * Shortcut when we get a request for the same device again. */ if (previous_cache_hit && previous_cache_hit->dev == dev) { - return previous_cache_hit; + mce = previous_cache_hit; + goto ok_out; } /** - * Lock the cache while we walk it. + * Initialize the cache if that was not done before. */ - P(mntent_cache_lock); + 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(); + } + } 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) { + initialize_mntent_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; } - /** - * We are done walking the cache. - */ +ok_out: V(mntent_cache_lock); return mce; }