]> git.sur5r.net Git - bacula/bacula/commitdiff
Enhance mountcache with rescan option after interval.
authorMarco van Wieringen <mvw@planets.elm.net>
Fri, 11 Nov 2011 09:15:02 +0000 (10:15 +0100)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:50:13 +0000 (14:50 +0200)
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
bacula/src/lib/mntent_cache.h

index 7db44759868ff3745089b0dc874f4e0f64fb36fa..2c68bdcefcf8be46de449b530de91b2fa79391ef 100644 (file)
@@ -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;
    }
index 36bd5243e04f444909761799c3bc96b2c2c925b1..82c2f64f1f3fec8f818a371a31d395f32fe85937 100644 (file)
 #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 */