DO NOT TRY THIS AT HOME
I am having a weird issue with std::filesystem::remove_all
.
I have written a program that writes N
files to disk in a single directory and then deletes all the files afterward (there is a good reason for this).
However, when I use std::filesystem::remove_all
I get errors like this:
filesystem error: cannot remove all: Structure needs cleaning [./tmp_storage] [./tmp_storage/2197772]
and the folder is not delete (obviously the call failed) and calling ls
after shows that the file system is "damaged":
$ ls tmp_storage/
ls: cannot access 'tmp_storage/2197772': Structure needs cleaning
ls: cannot access 'tmp_storage/5493417': Structure needs cleaning
...
and I have to repair the file system. The fully program looks like this:
#include <fmt/core.h>
#include <CLI/CLI.hpp>
#include <filesystem>
#include <fstream>
#include <string>
#include <exception>
int main(int argc, char** argv)
{
size_t num_files{64000000};
CLI::App app("Writes N number of files to dir in file system to check the maximum number of files in a directory");
app.add_option("-c,--count", num_files, fmt::format("How many files generate [Default: {}]", num_files));
CLI11_PARSE(app, argc, argv);
std::string base_path = "./tmp_storage";
if (!std::filesystem::exists(base_path))
{
std::filesystem::create_directory(base_path);
}
size_t i;
for (i = 1; i <= num_files; ++i)
{
std::string file_path = fmt::format("{}/{}", base_path, std::to_string(i));
std::ofstream out(file_path, std::ios::binary);
if (out.fail())
{
break;
}
try
{
out << std::to_string(i);
}
catch(const std::exception& e)
{
fmt::print("{}\n", e.what());
}
}
fmt::print("Wrote {} out of {} files\n", i, num_files);
try
{
std::filesystem::remove_all(base_path);
}
catch(const std::exception& e)
{
fmt::print("{}\n", e.what());
}
fmt::print("Done\n");
return 0;
}
Compiled with the following Makefile:
CC = clang++
CXX_FLAGS = -std=c++17
LINK_FLAGS = -lfmt
all:
$(CC) $(CXX_FLAGS) main.cpp -o main $(LINK_FLAGS)
I have been able to replicate the behavior on Fedora Server 33/34 and Ubuntu with Fedora using XFS and Ubuntu using EXT4 and XFS.
Is this a bug in std::filesystem::remov_all
or am I doing something wrong?
For Fedora the kernel version is: Linux 5.12.12-300.fc34.x86_64 x86_64
with clang version
clang version 12.0.0 (Fedora 12.0.0-2.fc34)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin