summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/InodeCache.cpp45
-rw-r--r--src/InodeCache.hpp6
2 files changed, 41 insertions, 10 deletions
diff --git a/src/InodeCache.cpp b/src/InodeCache.cpp
index e6245fa6..17e92417 100644
--- a/src/InodeCache.cpp
+++ b/src/InodeCache.cpp
@@ -20,7 +20,6 @@
#include "Config.hpp"
#include "Digest.hpp"
-#include "Fd.hpp"
#include "Finalizer.hpp"
#include "Hash.hpp"
#include "Logging.hpp"
@@ -29,8 +28,6 @@
#include "Util.hpp"
#include "fmtmacros.hpp"
-#include <util/TimePoint.hpp>
-
#include <fcntl.h>
#include <libgen.h>
#include <sched.h>
@@ -78,6 +75,14 @@ const uint32_t k_num_entries = 4;
// Maximum time the spin lock loop will try before giving up.
const auto k_max_lock_duration = util::Duration(5);
+// The memory-mapped file may reside on a filesystem with compression. Memory
+// accesses to the file risk crashing if such a filesystem gets full, so stop
+// using the inode cache well before this happens.
+const uint64_t k_min_fs_mib_left = 100; // 100 MiB
+
+// How long a filesystem space check is valid before we make a new one.
+const util::Duration k_fs_space_check_valid_duration(1);
+
static_assert(Digest::size() == 20,
"Increment version number if size of digest is changed.");
static_assert(std::is_trivially_copyable<Digest>::value,
@@ -229,17 +234,21 @@ InodeCache::mmap_file(const std::string& inode_cache_file)
munmap(m_sr, sizeof(SharedRegion));
m_sr = nullptr;
}
- Fd fd(open(inode_cache_file.c_str(), O_RDWR));
- if (!fd) {
+ m_fd = Fd(open(inode_cache_file.c_str(), O_RDWR));
+ if (!m_fd) {
LOG("Failed to open inode cache {}: {}", inode_cache_file, strerror(errno));
return false;
}
- if (!fd_is_on_known_to_work_file_system(*fd)) {
+ if (!fd_is_on_known_to_work_file_system(*m_fd)) {
return false;
}
- SharedRegion* sr = reinterpret_cast<SharedRegion*>(mmap(
- nullptr, sizeof(SharedRegion), PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0));
- fd.close();
+ SharedRegion* sr =
+ reinterpret_cast<SharedRegion*>(mmap(nullptr,
+ sizeof(SharedRegion),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ *m_fd,
+ 0));
if (sr == MMAP_FAILED) {
LOG("Failed to mmap {}: {}", inode_cache_file, strerror(errno));
return false;
@@ -387,6 +396,24 @@ InodeCache::initialize()
return false;
}
+ if (m_fd) {
+ auto now = util::TimePoint::now();
+ if (now > m_last_fs_space_check + k_fs_space_check_valid_duration) {
+ m_last_fs_space_check = now;
+
+ struct statfs buf;
+ if (fstatfs(*m_fd, &buf) != 0) {
+ LOG("fstatfs failed: {}", strerror(errno));
+ return false;
+ }
+ if (buf.f_bavail * 512 < k_min_fs_mib_left * 1024 * 1024) {
+ LOG("Filesystem has less than {} MiB free space, not using inode cache",
+ k_min_fs_mib_left);
+ return false;
+ }
+ }
+ }
+
if (m_sr) {
return true;
}
diff --git a/src/InodeCache.hpp b/src/InodeCache.hpp
index c4e8c4ea..5819ed07 100644
--- a/src/InodeCache.hpp
+++ b/src/InodeCache.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
@@ -18,7 +18,9 @@
#pragma once
+#include <Fd.hpp>
#include <util/Duration.hpp>
+#include <util/TimePoint.hpp>
#include <cstdint>
#include <functional>
@@ -130,7 +132,9 @@ private:
const Config& m_config;
util::Duration m_min_age;
+ Fd m_fd;
struct SharedRegion* m_sr = nullptr;
bool m_failed = false;
const pid_t m_self_pid;
+ util::TimePoint m_last_fs_space_check;
};