]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/mntent_cache.c
Update version + date
[bacula/bacula] / bacula / src / lib / mntent_cache.c
index 14422c040356a842770a518d62fb564e17a43895..c30cc912fee6008b80e548a6dad533bf736496f7 100644 (file)
@@ -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,27 @@ 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;
+
+static const char *skipped_fs_types[] = {
+#if defined(HAVE_LINUX_OS)
+   "rootfs",
+#endif
+   NULL
+};
+
 /**
  * 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;
@@ -145,6 +160,18 @@ static void add_mntent_mapping(uint32_t dev, const char *special, const char *mo
    mntent_cache_entry_hashtable->insert(mce->dev, mce);
 }
 
+static inline bool skip_fstype(const char *fstype)
+{
+   int i;
+
+   for (i = 0; skipped_fs_types[i]; i++) {
+      if (bstrcmp(fstype, skipped_fs_types[i]))
+         return true;
+   }
+
+   return false;
+}
+
 /**
  * OS specific function to load the different mntents into the cache.
  * This function should be called with a write lock on the mntent_cache.
@@ -178,6 +205,10 @@ static void refresh_mount_cache(void)
 #endif
 
    while ((mnt = getmntent(fp)) != (struct mntent *)NULL) {
+      if (skip_fstype(mnt->mnt_type)) {
+         continue;
+      }
+
       if (stat(mnt->mnt_dir, &st) < 0) {
          continue;
       }
@@ -193,6 +224,10 @@ static void refresh_mount_cache(void)
       return;
 
    while (getmntent(fp, &mnt) == 0) {
+      if (skip_fstype(mnt.mnt_fstype)) {
+         continue;
+      }
+
       if (stat(mnt.mnt_mountp, &st) < 0) {
          continue;
       }
@@ -220,7 +255,8 @@ static void refresh_mount_cache(void)
 
    if ((cnt = getmntinfo(&mntinfo, flags)) > 0) {
       while (cnt > 0) {
-         if (stat(mntinfo->f_mntonname, &st) == 0) {
+         if (!skip_fstype(mntinfo->f_fstypename) &&
+             stat(mntinfo->f_mntonname, &st) == 0) {
             add_mntent_mapping(st.st_dev,
                                mntinfo->f_mntfromname,
                                mntinfo->f_mntonname,
@@ -254,6 +290,10 @@ static void refresh_mount_cache(void)
    while (cnt < n_entries) {
       vmp = (struct vmount *)current;
 
+      if (skip_fstype(ve->vfsent_name)) {
+         continue;
+      }
+
       if (stat(current + vmp->vmt_data[VMT_STUB].vmt_off, &st) < 0) {
          continue;
       }
@@ -291,6 +331,10 @@ static void refresh_mount_cache(void)
    cnt = 0;
    current = entries;
    while (cnt < n_entries) {
+      if (skip_fstype(current->f_fstypename)) {
+         continue;
+      }
+
       if (stat(current->f_mntonname, &st) < 0) {
          continue;
       }
@@ -340,14 +384,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 +397,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 +424,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;
 }