From 03d609a24b00d53b95a255753c74c9c02e840387 Mon Sep 17 00:00:00 2001 From: jsteemann Date: Thu, 10 Jun 2021 22:29:15 +0200 Subject: [PATCH] Backport rocksdb diskspace bugfix * Backport bugfix from upstream rocksdb repository for calculating the free disk space for the database directory. Before the bugfix, rocksdb could overestimate the amount of free space when the arangod process was run as non-privileged users. --- 3rdParty/rocksdb/6.8/env/fs_posix.cc | 12 +++++++++++- CHANGELOG | 5 +++++ arangod/RocksDBEngine/RocksDBEngine.cpp | 11 +++++++++++ lib/Basics/files.cpp | 14 ++++++++++++-- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/3rdParty/rocksdb/6.8/env/fs_posix.cc b/3rdParty/rocksdb/6.8/env/fs_posix.cc index 966145575591..4014a9479fd5 100644 --- a/3rdParty/rocksdb/6.8/env/fs_posix.cc +++ b/3rdParty/rocksdb/6.8/env/fs_posix.cc @@ -832,7 +832,17 @@ class PosixFileSystem : public FileSystem { return IOError("While doing statvfs", fname, errno); } - *free_space = ((uint64_t)sbuf.f_bsize * sbuf.f_bfree); + // sbuf.bfree is total free space available to root + // sbuf.bavail is total free space available to unprivileged user + // sbuf.bavail <= sbuf.bfree ... pick correct based upon effective user id + if (geteuid()) { + // non-zero user is unprivileged, or -1 if error. take more conservative + // size + *free_space = ((uint64_t)sbuf.f_bsize * sbuf.f_bavail); + } else { + // root user can access all disk space + *free_space = ((uint64_t)sbuf.f_bsize * sbuf.f_bfree); + } return IOStatus::OK(); } diff --git a/CHANGELOG b/CHANGELOG index d9eb94ea142d..1b06467129a3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ devel ----- +* Backport bugfix from upstream rocksdb repository for calculating the + free disk space for the database directory. Before the bugfix, rocksdb + could overestimate the amount of free space when the arangod process + was run as non-privileged users. + * Add soft coordinator shutdown: This is a new option `soft=true` for the DELETE /_admin/shutdown API. Has only meaning for coordinators, otherwise ignored. A number of things are allowed to finish but no new things are diff --git a/arangod/RocksDBEngine/RocksDBEngine.cpp b/arangod/RocksDBEngine/RocksDBEngine.cpp index e86d51a80658..8220a5dd7547 100644 --- a/arangod/RocksDBEngine/RocksDBEngine.cpp +++ b/arangod/RocksDBEngine/RocksDBEngine.cpp @@ -479,6 +479,17 @@ void RocksDBEngine::start() { FATAL_ERROR_EXIT(); } } + + uint64_t totalSpace; + uint64_t freeSpace; + if (TRI_GetDiskSpaceInfo(_path, totalSpace, freeSpace).ok() && totalSpace != 0) { + LOG_TOPIC("b71b9", DEBUG, arangodb::Logger::ENGINES) + << "total disk space for database directory mount: " + << basics::StringUtils::formatSize(totalSpace) + << ", free disk space for database directory mount: " + << basics::StringUtils::formatSize(freeSpace) + << " (" << (100.0 * double(freeSpace) / double(totalSpace)) << "% free)"; + } // options imported set by RocksDBOptionFeature auto const& opts = server().getFeature(); diff --git a/lib/Basics/files.cpp b/lib/Basics/files.cpp index 0a4ee833ad75..94e8e6c91211 100644 --- a/lib/Basics/files.cpp +++ b/lib/Basics/files.cpp @@ -2643,8 +2643,18 @@ arangodb::Result TRI_GetDiskSpaceInfo(std::string const& path, TRI_set_errno(TRI_ERROR_SYS_ERROR); return {TRI_errno(), TRI_last_error()}; } - totalSpace = static_cast(stat.f_frsize) * static_cast(stat.f_blocks); - freeSpace = static_cast(stat.f_frsize) * static_cast(stat.f_bfree); + totalSpace = static_cast(stat.f_bsize) * static_cast(stat.f_blocks); + + // sbuf.bfree is total free space available to root + // sbuf.bavail is total free space available to unprivileged user + // sbuf.bavail <= sbuf.bfree ... pick correct based upon effective user id + if (geteuid()) { + // non-zero user is unprivileged, or -1 if error. take more conservative size + freeSpace = static_cast(stat.f_bsize) * static_cast(stat.f_bavail); + } else { + // root user can access all disk space + freeSpace = static_cast(stat.f_bsize) * static_cast(stat.f_bfree); + } #endif return {}; }