/*
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.
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.
* - 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.
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);
}
/**
#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)
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) {
#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,
*/
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.
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);
}
}
*/
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();
}
*/
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;
}