/*
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.
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;
/**
* 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.)
*/
* 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);
}
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;
}