diff --git a/src/or/conscache.c b/src/or/conscache.c
index c30d1998c6..350a05b0f2 100644
--- a/src/or/conscache.c
+++ b/src/or/conscache.c
@@ -54,6 +54,11 @@ struct consensus_cache_t {
storage_dir_t *dir;
/** List of all the entries in the directory. */
smartlist_t *entries;
+
+ /** The maximum number of entries that we'd like to allow in this cache.
+ * This is the same as the storagedir limit when MUST_UNMAP_TO_UNLINK is
+ * not defined. */
+ unsigned max_entries;
};
static void consensus_cache_clear(consensus_cache_t *cache);
@@ -71,6 +76,10 @@ consensus_cache_open(const char *subdir, int max_entries)
{
consensus_cache_t *cache = tor_malloc_zero(sizeof(consensus_cache_t));
char *directory = get_datadir_fname(subdir);
+ cache->max_entries = max_entries;
+#ifdef MUST_UNMAP_TO_UNLINK
+ max_entries = 1000000;
+#endif
cache->dir = storage_dir_new(directory, max_entries);
tor_free(directory);
if (!cache->dir) {
@@ -82,6 +91,19 @@ consensus_cache_open(const char *subdir, int max_entries)
return cache;
}
+/** Return true if it's okay to put more entries in this cache than
+ * its official file limit. */
+int
+consensus_cache_may_overallocate(consensus_cache_t *cache)
+{
+ (void) cache;
+#ifdef MUST_UNMAP_TO_UNLINK
+ return 1;
+#else
+ return 0;
+#endif
+}
+
/**
* Tell the sandbox (if any) configured by cfg to allow the
* operations that cache will need.
@@ -90,6 +112,11 @@ int
consensus_cache_register_with_sandbox(consensus_cache_t *cache,
struct sandbox_cfg_elem **cfg)
{
+#ifdef MUST_UNMAP_TO_UNLINK
+ /* Our sandbox doesn't support huge limits like we use here.
+ */
+ tor_assert_nonfatal_unreached();
+#endif
return storage_dir_register_with_sandbox(cache->dir, cfg);
}
diff --git a/src/or/conscache.h b/src/or/conscache.h
index aef54201f0..a0d74c4e08 100644
--- a/src/or/conscache.h
+++ b/src/or/conscache.h
@@ -14,6 +14,7 @@ HANDLE_DECL(consensus_cache_entry, consensus_cache_entry_t, )
consensus_cache_t *consensus_cache_open(const char *subdir, int max_entries);
void consensus_cache_free(consensus_cache_t *cache);
struct sandbox_cfg_elem;
+int consensus_cache_may_overallocate(consensus_cache_t *cache);
int consensus_cache_register_with_sandbox(consensus_cache_t *cache,
struct sandbox_cfg_elem **cfg);
void consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff);
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c
index 928fc26f54..831d5d45c3 100644
--- a/src/or/consdiffmgr.c
+++ b/src/or/consdiffmgr.c
@@ -1136,7 +1136,7 @@ consdiffmgr_ensure_space_for_files(int n)
return 0;
}
// Let's get more assertive: clean out unused stuff, and force-remove
- // the files.
+ // the files that we can.
consdiffmgr_cleanup();
consensus_cache_delete_pending(cache, 1);
const int n_to_remove = n - consensus_cache_get_n_filenames_available(cache);
@@ -1159,6 +1159,14 @@ consdiffmgr_ensure_space_for_files(int n)
smartlist_free(objects);
consensus_cache_delete_pending(cache, 1);
+
+ if (consensus_cache_may_overallocate(cache)) {
+ /* If we're allowed to throw extra files into the cache, let's do so
+ * rather getting upset.
+ */
+ return 0;
+ }
+
if (BUG(n_marked < n_to_remove))
return -1;
else