]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/mntent_cache.c
update version
[bacula/bacula] / bacula / src / lib / mntent_cache.c
index 11094886d511a23e3e2c1e54153ed38437b28953..7db44759868ff3745089b0dc874f4e0f64fb36fa 100644 (file)
@@ -1,12 +1,12 @@
 /*
    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.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
@@ -15,7 +15,7 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
@@ -41,7 +41,7 @@
  * - DARWIN (OSX)
  * - IRIX
  * - AIX
- * - OSF1 (True64)
+ * - OSF1 (Tru64)
  * - Solaris
  *
  * Currently we only use this code for Linux and OSF1 based fstype determination.
 #include <sys/stat.h>
 
 #if defined(HAVE_GETMNTENT)
-#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS)
+#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS) || defined(HAVE_AIX_OS)
 #include <mntent.h>
 #elif defined(HAVE_SUN_OS)
 #include <sys/mnttab.h>
 #endif /* HAVE_GETMNTENT */
 #elif defined(HAVE_GETMNTINFO)
-#if defined(HAVE_DARWIN_OS)
+#if defined(HAVE_OPENBSD_OS)
 #include <sys/param.h>
-#include <sys/ucred.h> 
-#include <sys/mount.h> 
-#else
+#include <sys/mount.h>
+#elif defined(HAVE_NETBSD_OS)
 #include <sys/types.h>
 #include <sys/statvfs.h>
+#else
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
 #endif
 #elif defined(HAVE_AIX_OS)
 #include <fshelp.h>
 #include <sys/mount.h>
 #endif
 
-static char cache_initialized = 0;
-
-/**
+/*
  * Protected data by mutex lock.
  */
 static pthread_mutex_t mntent_cache_lock = PTHREAD_MUTEX_INITIALIZER;
-static mntent_cache_entry_t *mntent_cache_entry_hashtable[NR_MNTENT_CACHE_ENTRIES];
 static mntent_cache_entry_t *previous_cache_hit = NULL;
-
-/**
- * Simple hash function.
- */
-static uint32_t mntent_hash_function(uint32_t dev)
-{
-   return (dev % NR_MNTENT_CACHE_ENTRIES);
-}
+static htable *mntent_cache_entry_hashtable = NULL;
 
 /**
  * Add a new entry to the cache.
@@ -113,38 +106,43 @@ static uint32_t mntent_hash_function(uint32_t dev)
 static void add_mntent_mapping(uint32_t dev, const char *special, const char *mountpoint,
                                const char *fstype, const char *mntopts)
 {
-   uint32_t hash;
+   int len;
    mntent_cache_entry_t *mce;
 
-   /**
-    * Select the correct hash bucket.
-    */
-   hash = mntent_hash_function(dev);
-
-   /**
-    * See if this is the first being put into the hash bucket.
+   /*
+    * Calculate the length of all strings so we can allocate the buffer
+    * as one big chunk of memory using the hash_malloc method.
     */
-   if (mntent_cache_entry_hashtable[hash] == (mntent_cache_entry_t *)NULL) {
-      mce = (mntent_cache_entry_t *)malloc(sizeof(mntent_cache_entry_t));
-      memset((caddr_t)mce, 0, sizeof(mntent_cache_entry_t));
-      mntent_cache_entry_hashtable[hash] = mce;
-   } else {
-      /**
-       * Walk the linked list in the hash bucket.
-       */
-      for (mce = mntent_cache_entry_hashtable[hash]; mce->next != NULL; mce = mce->next) ;
-      mce->next = (mntent_cache_entry_t *)malloc(sizeof(mntent_cache_entry_t));
-      mce = mce->next;
-      memset((caddr_t)mce, 0, sizeof(mntent_cache_entry_t));
+   len = strlen(special) + 1;
+   len += strlen(mountpoint) + 1;
+   len += strlen(fstype) + 1;
+   if (mntopts) {
+      len += strlen(mntopts) + 1;
    }
 
+   /*
+    * We allocate all members of the hash entry in the same memory chunk.
+    */
+   mce = (mntent_cache_entry_t *)mntent_cache_entry_hashtable->hash_malloc(sizeof(mntent_cache_entry_t) + len);
    mce->dev = dev;
-   mce->special = bstrdup(special);
-   mce->mountpoint = bstrdup(mountpoint);
-   mce->fstype = bstrdup(fstype);
+
+   mce->special = (char *)mce + sizeof(mntent_cache_entry_t);
+   strcpy(mce->special, special);
+
+   mce->mountpoint = mce->special + strlen(mce->special) + 1;
+   strcpy(mce->mountpoint, mountpoint);
+
+   mce->fstype = mce->mountpoint + strlen(mce->mountpoint) + 1;
+   strcpy(mce->fstype, fstype);
+
    if (mntopts) {
-      mce->mntopts = bstrdup(mntopts);
+      mce->mntopts = mce->fstype + strlen(mce->fstype) + 1;
+      strcpy(mce->mntopts, mntopts);
+   } else {
+      mce->mntopts = NULL;
    }
+
+   mntent_cache_entry_hashtable->insert(mce->dev, mce);
 }
 
 /**
@@ -156,7 +154,7 @@ static void refresh_mount_cache(void)
 #if defined(HAVE_GETMNTENT)
    FILE *fp;
    struct stat st;
-#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS) || defined(HAVE_IRIX_OS)
+#if defined(HAVE_LINUX_OS) || defined(HAVE_HPUX_OS) || defined(HAVE_IRIX_OS) || defined(HAVE_AIX_OS)
    struct mntent *mnt;
 
 #if defined(HAVE_LINUX_OS)
@@ -173,6 +171,10 @@ static void refresh_mount_cache(void)
    if ((fp = setmntent(MOUNTED, "r")) == (FILE *)NULL) {
       return;
    }
+#elif defined(HAVE_AIX_OS)
+   if ((fp = setmntent(MNTTAB, "r")) == (FILE *)NULL) {
+      return;
+   }
 #endif
 
    while ((mnt = getmntent(fp)) != (struct mntent *)NULL) {
@@ -203,13 +205,20 @@ static void refresh_mount_cache(void)
 #elif defined(HAVE_GETMNTINFO)
    int cnt;
    struct stat st;
-#if defined(HAVE_DARWIN_OS)
+#if defined(HAVE_NETBSD_OS)
+   struct statvfs *mntinfo;
+#else
    struct statfs *mntinfo;
+#endif
+#if defined(ST_NOWAIT)
+   int flags = ST_NOWAIT;
+#elif defined(MNT_NOWAIT)
+   int flags = MNT_NOWAIT;
 #else
-   struct statvfs *mntinfo;
+   int flags = 0;
 #endif
 
-   if ((cnt = getmntinfo(&mntinfo, MNT_NOWAIT)) > 0) {
+   if ((cnt = getmntinfo(&mntinfo, flags)) > 0) {
       while (cnt > 0) {
          if (stat(mntinfo->f_mntonname, &st) == 0) {
             add_mntent_mapping(st.st_dev,
@@ -303,15 +312,16 @@ static void refresh_mount_cache(void)
  */
 static void clear_mount_cache()
 {
-   uint32_t hash;
-   mntent_cache_entry_t *mce, *mce_next;
+   mntent_cache_entry_t *mce = NULL;
 
-   if (cache_initialized == 0) {
+   if (!mntent_cache_entry_hashtable) {
       /**
        * Initialize the hash table.
        */
-      memset((caddr_t)mntent_cache_entry_hashtable, 0, NR_MNTENT_CACHE_ENTRIES * sizeof(mntent_cache_entry_t *));
-      cache_initialized = 1;
+      mntent_cache_entry_hashtable = (htable *)malloc(sizeof(htable));
+      mntent_cache_entry_hashtable->init(mce, &mce->link,
+                                         NR_MNTENT_CACHE_ENTRIES,
+                                         NR_MNTENT_HTABLE_PAGES);
    } else {
       /**
        * Clear the previous_cache_hit.
@@ -319,33 +329,12 @@ static void clear_mount_cache()
       previous_cache_hit = NULL;
 
       /**
-       * Walk all hash buckets.
+       * Destroy the current content and (re)initialize the hashtable.
        */
-      for (hash = 0; hash < NR_MNTENT_CACHE_ENTRIES; hash++) {
-         /**
-          * Walk the content of this hash bucket.
-          */
-         mce = mntent_cache_entry_hashtable[hash];
-         mntent_cache_entry_hashtable[hash] = NULL;
-         while (mce != NULL) {
-            /**
-             * Save the pointer to the next entry.
-             */
-            mce_next = mce->next;
-
-            /**
-             * Free the structure.
-             */
-            if (mce->mntopts)
-               free(mce->mntopts);
-            free(mce->fstype);
-            free(mce->mountpoint);
-            free(mce->special);
-            free(mce);
-
-            mce = mce_next;
-         }
-      }
+      mntent_cache_entry_hashtable->destroy();
+      mntent_cache_entry_hashtable->init(mce, &mce->link,
+                                         NR_MNTENT_CACHE_ENTRIES,
+                                         NR_MNTENT_HTABLE_PAGES);
    }
 }
 
@@ -403,13 +392,12 @@ void flush_mntent_cache(void)
  */
 mntent_cache_entry_t *find_mntent_mapping(uint32_t dev)
 {
-   uint32_t hash;
-   mntent_cache_entry_t *mce;
+   mntent_cache_entry_t *mce = NULL;
 
    /**
     * Initialize the cache if that was not done before.
     */
-   if (cache_initialized == 0) {
+   if (!mntent_cache_entry_hashtable) {
       initialize_mntent_cache();
    }
 
@@ -425,25 +413,14 @@ mntent_cache_entry_t *find_mntent_mapping(uint32_t dev)
     */
    P(mntent_cache_lock);
 
-   /**
-    * Select the correct hash bucket.
-    */
-   hash = mntent_hash_function(dev);
-
-   /**
-    * Walk the hash bucket.
-    */
-   for (mce = mntent_cache_entry_hashtable[hash]; mce != NULL; mce = mce->next) {
-      if (mce->dev == dev) {
-         previous_cache_hit = mce;
-         V(mntent_cache_lock);
-         return mce;
-      }
+   mce = (mntent_cache_entry_t *)mntent_cache_entry_hashtable->lookup(dev);
+   if (mce) {
+      previous_cache_hit = mce;
    }
 
    /**
     * We are done walking the cache.
     */
    V(mntent_cache_lock);
-   return NULL;
+   return mce;
 }