Skip to content

Commit

Permalink
file: add file_system_stat
Browse files Browse the repository at this point in the history
Return an abstract file_system_stat_data representing
the system statvfs for the filesystem identified
by the given file name.

The motivation is implementing a disk-space monitor
in scylladb.

Signed-off-by: Benny Halevy <[email protected]>
  • Loading branch information
bhalevy committed Nov 10, 2024
1 parent 3db2d8e commit afdd470
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
16 changes: 16 additions & 0 deletions include/seastar/core/file-types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,22 @@ struct stat_data {
std::chrono::system_clock::time_point time_changed; // Time of last status change (either content or attributes)
};

/// Filesystem-wide stat information
/// See statvfs(3)
struct file_system_stat_data {
size_t block_size; // Filesystem block size
size_t fragment_size; // Fragment size
uint64_t size_in_bytes; // Size of filesystem in bytes
uint64_t free_bytes; // Free space in bytes
uint64_t available_bytes; // Available space in bytes for unprivileged users
uint64_t files_total; // Number of inodes
uint64_t files_free; // Number of free inodes
uint64_t files_available; // Number of free inodes for unprivileged users
uint64_t fsid; // Filesystem ID
uint64_t mount_flags; // Mount flags
size_t max_filename_length; // Maximum filename length
};

/// @}

SEASTAR_MODULE_EXPORT_END
Expand Down
5 changes: 5 additions & 0 deletions include/seastar/core/seastar.hh
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ future<uint64_t> fs_avail(std::string_view name) noexcept;
future<uint64_t> fs_free(std::string_view name) noexcept;
/// @}

/// Return filesystem-wide stat where a file is located.
///
/// \param name name of the file to inspect
future<file_system_stat_data> file_system_stat(std::string_view name) noexcept;

namespace experimental {
/// \defgroup interprocess-module Interprocess Communication
///
Expand Down
18 changes: 18 additions & 0 deletions src/util/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
module;
#endif

#include <coroutine>
#include <cstdint>
#include <deque>
#include <filesystem>
Expand Down Expand Up @@ -128,6 +129,23 @@ future<uint64_t> fs_free(std::string_view name) noexcept {
});
}

future<file_system_stat_data> file_system_stat(std::string_view name) noexcept {
struct statvfs st = co_await engine().statvfs(name);
co_return file_system_stat_data{
.block_size = st.f_bsize,
.fragment_size = st.f_frsize,
.size_in_bytes = (uint64_t)st.f_blocks * st.f_frsize,
.free_bytes = (uint64_t)st.f_bfree * st.f_frsize,
.available_bytes = (uint64_t)st.f_bavail * st.f_frsize,
.files_total = st.f_files,
.files_free = st.f_ffree,
.files_available = st.f_favail,
.fsid = st.f_fsid,
.mount_flags = st.f_flag,
.max_filename_length = st.f_namemax,
};
}

future<stat_data> file_stat(std::string_view name, follow_symlink follow) noexcept {
return engine().file_stat(name, follow);
}
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/file_io_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -947,3 +947,13 @@ SEASTAR_TEST_CASE(test_oversized_io_works) {
BOOST_REQUIRE((size_t)std::count_if(buf.get(), buf.get() + buf_size, [](auto x) { return x == 'a'; }) == buf_size);
});
}

SEASTAR_TEST_CASE(test_file_system_stat) {
return tmp_dir::do_with_thread([] (tmp_dir& t) {
const auto& name = t.get_path().native();
auto fs_stat = file_system_stat(name).get();

BOOST_REQUIRE_GE(fs_stat.size_in_bytes, fs_stat.free_bytes);
BOOST_REQUIRE_GE(fs_stat.free_bytes, fs_stat.available_bytes);
});
}

0 comments on commit afdd470

Please sign in to comment.