cephfs-tool: Add filesystem statistics reporting before and after benchmark runs

Added filesystem stats reporting to cephfs-tool.cc.

Helper functions
• fetch_statvfs() — uses ceph_ll_statfs on the root inode when --async-io
  is set, otherwise ceph_statfs on mount_root
• report_fs_stats() — prints and optionally JSON-encodes:
  • Total / free blocks
  • File count

When it runs
• Before the iteration loop (after the bench directory is created)
• After all iterations finish (before the final report and optional cleanup)

Console output example

Filesystem statistics (before iterations):
  Total blocks:      ...
  Free blocks:       ...
  Files:             ...

JSON output (when --json is used) adds a filesystem_stats section with before
and after objects containing the same fields.

Fixes: https://tracker.ceph.com/issues/76183
Signed-off-by: Edwin Rodriguez <edwin.rodriguez1@ibm.com>
This commit is contained in:
Edwin Rodriguez 2026-06-18 10:14:43 -04:00
parent d9dbfde2b7
commit c8d115ee5d

View File

@ -40,6 +40,7 @@
// Standard Public Ceph API
#include <cephfs/libcephfs.h>
#include <fcntl.h>
#include <sys/statvfs.h>
#include <unistd.h>
// Boost Program Options
@ -1221,6 +1222,54 @@ print_statistics(
}
}
static void dump_statvfs_json(ceph::Formatter* f, const struct statvfs& st)
{
f->dump_unsigned("block_size", st.f_bsize);
f->dump_unsigned("total_blocks", st.f_blocks);
f->dump_unsigned("free_blocks", st.f_bfree);
f->dump_unsigned("files", st.f_files);
}
static int fetch_statvfs(struct ceph_mount_info* cmount,
const BenchConfig& config,
struct statvfs* stbuf)
{
if (config.async_io) {
Inode* root = nullptr;
int rc = ceph_ll_lookup_root(cmount, &root);
if (rc < 0) {
return rc;
}
return ceph_ll_statfs(cmount, root, stbuf);
}
return ceph_statfs(cmount, config.mount_root.c_str(), stbuf);
}
static void report_fs_stats(const char* phase,
struct ceph_mount_info* cmount,
const BenchConfig& config,
ceph::Formatter* json_formatter)
{
struct statvfs stbuf = {};
int rc = fetch_statvfs(cmount, config, &stbuf);
if (rc < 0) {
cerr << "Failed to get filesystem stats (" << phase << "): "
<< strerror(-rc) << std::endl;
return;
}
cout << "\nFilesystem statistics (" << phase << " iterations):" << std::endl;
cout << " Total blocks: " << stbuf.f_blocks << std::endl;
cout << " Free blocks: " << stbuf.f_bfree << std::endl;
cout << " Files: " << stbuf.f_files << std::endl;
if (json_formatter) {
json_formatter->open_object_section(phase);
dump_statvfs_json(json_formatter, stbuf);
json_formatter->close_section();
}
}
// Helper to check for errors and print them
bool check_and_report_errors(const std::atomic<bool>& stop_signal,
const std::vector<std::stringstream>& outputs) {
@ -1366,6 +1415,11 @@ int do_bench(BenchConfig& config) {
int files_per_thread = config.num_files / config.num_threads;
int remainder = config.num_files % config.num_threads;
if (json_formatter) {
json_formatter->open_object_section("filesystem_stats");
}
report_fs_stats("before", shared_cmount, config, json_formatter.get());
std::vector<double> write_mbps;
std::vector<double> write_fps;
std::vector<double> read_mbps;
@ -1641,6 +1695,11 @@ int do_bench(BenchConfig& config) {
}
}
report_fs_stats("after", shared_cmount, config, json_formatter.get());
if (json_formatter) {
json_formatter->close_section(); // filesystem_stats
}
cout << std::endl << std::endl << "*** Final Report ***" << std::endl;
if (json_formatter) {