mirror of
https://github.com/Zygo/bees.git
synced 2025-08-03 06:13:29 +02:00
Compare commits
8 Commits
v0.11-rc4
...
a844024395
Author | SHA1 | Date | |
---|---|---|---|
|
a844024395 | ||
|
47243aef14 | ||
|
a670aa5a71 | ||
|
51b3bcdbe4 | ||
|
ae58401d53 | ||
|
3e7eb43b51 | ||
|
962d94567c | ||
|
6dbef5f27b |
@@ -78,9 +78,6 @@ enum btrfs_compression_type {
|
|||||||
#define BTRFS_SHARED_BLOCK_REF_KEY 182
|
#define BTRFS_SHARED_BLOCK_REF_KEY 182
|
||||||
#define BTRFS_SHARED_DATA_REF_KEY 184
|
#define BTRFS_SHARED_DATA_REF_KEY 184
|
||||||
#define BTRFS_BLOCK_GROUP_ITEM_KEY 192
|
#define BTRFS_BLOCK_GROUP_ITEM_KEY 192
|
||||||
#define BTRFS_FREE_SPACE_INFO_KEY 198
|
|
||||||
#define BTRFS_FREE_SPACE_EXTENT_KEY 199
|
|
||||||
#define BTRFS_FREE_SPACE_BITMAP_KEY 200
|
|
||||||
#define BTRFS_DEV_EXTENT_KEY 204
|
#define BTRFS_DEV_EXTENT_KEY 204
|
||||||
#define BTRFS_DEV_ITEM_KEY 216
|
#define BTRFS_DEV_ITEM_KEY 216
|
||||||
#define BTRFS_CHUNK_ITEM_KEY 228
|
#define BTRFS_CHUNK_ITEM_KEY 228
|
||||||
@@ -97,6 +94,18 @@ enum btrfs_compression_type {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BTRFS_FREE_SPACE_INFO_KEY
|
||||||
|
#define BTRFS_FREE_SPACE_INFO_KEY 198
|
||||||
|
#define BTRFS_FREE_SPACE_EXTENT_KEY 199
|
||||||
|
#define BTRFS_FREE_SPACE_BITMAP_KEY 200
|
||||||
|
#define BTRFS_FREE_SPACE_OBJECTID -11ULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BTRFS_BLOCK_GROUP_RAID1C4
|
||||||
|
#define BTRFS_BLOCK_GROUP_RAID1C3 (1ULL << 9)
|
||||||
|
#define BTRFS_BLOCK_GROUP_RAID1C4 (1ULL << 10)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BTRFS_DEFRAG_RANGE_START_IO
|
#ifndef BTRFS_DEFRAG_RANGE_START_IO
|
||||||
|
|
||||||
// For some reason uapi has BTRFS_DEFRAG_RANGE_COMPRESS and
|
// For some reason uapi has BTRFS_DEFRAG_RANGE_COMPRESS and
|
||||||
|
@@ -13,7 +13,7 @@ namespace crucible {
|
|||||||
hexdump(ostream &os, const V &v)
|
hexdump(ostream &os, const V &v)
|
||||||
{
|
{
|
||||||
const auto v_size = v.size();
|
const auto v_size = v.size();
|
||||||
const uint8_t* const v_data = reinterpret_cast<uint8_t*>(v.data());
|
const uint8_t* const v_data = reinterpret_cast<const uint8_t*>(v.data());
|
||||||
os << "V { size = " << v_size << ", data:\n";
|
os << "V { size = " << v_size << ", data:\n";
|
||||||
for (size_t i = 0; i < v_size; i += 8) {
|
for (size_t i = 0; i < v_size; i += 8) {
|
||||||
string hex, ascii;
|
string hex, ascii;
|
||||||
|
@@ -932,15 +932,9 @@ namespace crucible {
|
|||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_SHARED_BLOCK_REF_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_SHARED_BLOCK_REF_KEY),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_SHARED_DATA_REF_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_SHARED_DATA_REF_KEY),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_BLOCK_GROUP_ITEM_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_BLOCK_GROUP_ITEM_KEY),
|
||||||
#ifdef BTRFS_FREE_SPACE_INFO_KEY
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_INFO_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_INFO_KEY),
|
||||||
#endif
|
|
||||||
#ifdef BTRFS_FREE_SPACE_EXTENT_KEY
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_EXTENT_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_EXTENT_KEY),
|
||||||
#endif
|
|
||||||
#ifdef BTRFS_FREE_SPACE_BITMAP_KEY
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_BITMAP_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_BITMAP_KEY),
|
||||||
#endif
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_DEV_EXTENT_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_DEV_EXTENT_KEY),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_DEV_ITEM_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_DEV_ITEM_KEY),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_CHUNK_ITEM_KEY),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_CHUNK_ITEM_KEY),
|
||||||
@@ -972,9 +966,7 @@ namespace crucible {
|
|||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_CSUM_TREE_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_CSUM_TREE_OBJECTID),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_QUOTA_TREE_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_QUOTA_TREE_OBJECTID),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_UUID_TREE_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_UUID_TREE_OBJECTID),
|
||||||
#ifdef BTRFS_FREE_SPACE_TREE_OBJECTID
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_TREE_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_FREE_SPACE_TREE_OBJECTID),
|
||||||
#endif
|
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_BALANCE_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_BALANCE_OBJECTID),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_ORPHAN_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_ORPHAN_OBJECTID),
|
||||||
NTOA_TABLE_ENTRY_ENUM(BTRFS_TREE_LOG_OBJECTID),
|
NTOA_TABLE_ENTRY_ENUM(BTRFS_TREE_LOG_OBJECTID),
|
||||||
|
@@ -17,6 +17,7 @@ KillSignal=SIGTERM
|
|||||||
MemoryAccounting=true
|
MemoryAccounting=true
|
||||||
Nice=19
|
Nice=19
|
||||||
Restart=on-abnormal
|
Restart=on-abnormal
|
||||||
|
RuntimeDirectoryMode=0700
|
||||||
RuntimeDirectory=bees
|
RuntimeDirectory=bees
|
||||||
StartupCPUWeight=25
|
StartupCPUWeight=25
|
||||||
StartupIOWeight=25
|
StartupIOWeight=25
|
||||||
|
@@ -230,8 +230,10 @@ BeesContext::dedup(const BeesRangePair &brp_in)
|
|||||||
BeesAddress first_addr(brp.first.fd(), brp.first.begin());
|
BeesAddress first_addr(brp.first.fd(), brp.first.begin());
|
||||||
BeesAddress second_addr(brp.second.fd(), brp.second.begin());
|
BeesAddress second_addr(brp.second.fd(), brp.second.begin());
|
||||||
|
|
||||||
if (first_addr.get_physical_or_zero() == second_addr.get_physical_or_zero()) {
|
const auto first_gpoz = first_addr.get_physical_or_zero();
|
||||||
BEESLOGTRACE("equal physical addresses in dedup");
|
const auto second_gpoz = second_addr.get_physical_or_zero();
|
||||||
|
if (first_gpoz == second_gpoz) {
|
||||||
|
BEESLOGDEBUG("equal physical addresses " << first_addr << " and " << second_addr << " in dedup");
|
||||||
BEESCOUNT(bug_dedup_same_physical);
|
BEESCOUNT(bug_dedup_same_physical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -819,7 +819,8 @@ BeesHashTable::BeesHashTable(shared_ptr<BeesContext> ctx, string filename, off_t
|
|||||||
root_info.do_ioctl(m_ctx->root_fd());
|
root_info.do_ioctl(m_ctx->root_fd());
|
||||||
// Hash might not be a btrfs
|
// Hash might not be a btrfs
|
||||||
BtrfsIoctlFsInfoArgs hash_info;
|
BtrfsIoctlFsInfoArgs hash_info;
|
||||||
if (hash_info.do_ioctl_nothrow(m_fd)) return;
|
// If btrfs fs_info ioctl fails, it must be a different fs
|
||||||
|
if (!hash_info.do_ioctl_nothrow(m_fd)) return;
|
||||||
// If Hash is a btrfs, Root must be the same one
|
// If Hash is a btrfs, Root must be the same one
|
||||||
if (root_info.fsid() != hash_info.fsid()) return;
|
if (root_info.fsid() != hash_info.fsid()) return;
|
||||||
// Hash is on the same one, blacklist it
|
// Hash is on the same one, blacklist it
|
||||||
|
@@ -948,22 +948,24 @@ BeesScanModeExtent::SizeTier::find_next_extent()
|
|||||||
const auto search_calls = BtrfsIoctlSearchKey::s_calls - init_s_calls;
|
const auto search_calls = BtrfsIoctlSearchKey::s_calls - init_s_calls;
|
||||||
const auto search_loops = BtrfsIoctlSearchKey::s_loops - init_s_loops;
|
const auto search_loops = BtrfsIoctlSearchKey::s_loops - init_s_loops;
|
||||||
if (crawl_time.age() > 1) {
|
if (crawl_time.age() > 1) {
|
||||||
BEESLOGDEBUG(
|
if (loop_count) {
|
||||||
"loop_count " << loop_count
|
BEESLOGDEBUG(
|
||||||
<< " size_low_count " << size_low_count
|
"loop_count " << loop_count
|
||||||
<< " size_high_count " << size_high_count
|
<< " size_low_count " << size_low_count
|
||||||
<< " gen_low_count " << gen_low_count
|
<< " size_high_count " << size_high_count
|
||||||
<< " gen_high_count " << gen_high_count
|
<< " gen_low_count " << gen_low_count
|
||||||
<< " search_calls " << search_calls
|
<< " gen_high_count " << gen_high_count
|
||||||
<< " search_loops " << search_loops
|
<< " search_calls " << search_calls
|
||||||
<< " skips " << skip_count
|
<< " search_loops " << search_loops
|
||||||
<< " flops " << flop_count
|
<< " skips " << skip_count
|
||||||
<< " time " << crawl_time
|
<< " flops " << flop_count
|
||||||
<< " subvol " << m_subvol
|
<< " time " << crawl_time
|
||||||
<< " search/loop " << pretty(search_calls / loop_count)
|
<< " subvol " << m_subvol
|
||||||
<< " skip/loop " << (100 * skip_count / loop_count) << "%"
|
<< " search/loop " << pretty(search_calls / loop_count)
|
||||||
<< " flop/loop " << (100 * flop_count / loop_count) << "%"
|
<< " skip/loop " << (100 * skip_count / loop_count) << "%"
|
||||||
);
|
<< " flop/loop " << (100 * flop_count / loop_count) << "%"
|
||||||
|
);
|
||||||
|
}
|
||||||
if (debug_oss) {
|
if (debug_oss) {
|
||||||
BEESLOGDEBUG("debug oss trace:\n" << debug_oss->str());
|
BEESLOGDEBUG("debug oss trace:\n" << debug_oss->str());
|
||||||
}
|
}
|
||||||
@@ -2013,7 +2015,7 @@ BeesRoots::open_root_nocache(uint64_t rootid)
|
|||||||
BEESCOUNT(root_parent_open_try);
|
BEESCOUNT(root_parent_open_try);
|
||||||
Fd parent_fd = open_root(parent_rootid);
|
Fd parent_fd = open_root(parent_rootid);
|
||||||
if (!parent_fd) {
|
if (!parent_fd) {
|
||||||
BEESLOGTRACE("no parent_fd");
|
BEESLOGDEBUG("no parent_fd for " << parent_rootid);
|
||||||
BEESCOUNT(root_parent_open_fail);
|
BEESCOUNT(root_parent_open_fail);
|
||||||
return Fd();
|
return Fd();
|
||||||
}
|
}
|
||||||
@@ -2036,7 +2038,7 @@ BeesRoots::open_root_nocache(uint64_t rootid)
|
|||||||
BEESTRACE("dirid " << dirid << " path " << ino.m_paths.at(0));
|
BEESTRACE("dirid " << dirid << " path " << ino.m_paths.at(0));
|
||||||
parent_fd = bees_openat(parent_fd, ino.m_paths.at(0).c_str(), FLAGS_OPEN_DIR);
|
parent_fd = bees_openat(parent_fd, ino.m_paths.at(0).c_str(), FLAGS_OPEN_DIR);
|
||||||
if (!parent_fd) {
|
if (!parent_fd) {
|
||||||
BEESLOGTRACE("no parent_fd from dirid");
|
BEESLOGDEBUG("no parent_fd from dirid " << dirid << " in parent_rootid " << parent_rootid);
|
||||||
BEESCOUNT(root_parent_path_open_fail);
|
BEESCOUNT(root_parent_path_open_fail);
|
||||||
return Fd();
|
return Fd();
|
||||||
}
|
}
|
||||||
@@ -2044,7 +2046,7 @@ BeesRoots::open_root_nocache(uint64_t rootid)
|
|||||||
BEESTRACE("openat(" << name_fd(parent_fd) << ", " << name << ")");
|
BEESTRACE("openat(" << name_fd(parent_fd) << ", " << name << ")");
|
||||||
Fd rv = bees_openat(parent_fd, name.c_str(), FLAGS_OPEN_DIR);
|
Fd rv = bees_openat(parent_fd, name.c_str(), FLAGS_OPEN_DIR);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
BEESLOGTRACE("open failed for name " << name << ": " << strerror(errno));
|
BEESLOGDEBUG("open failed for name " << name << " in parent_fd " << name_fd(parent_fd) << ": " << strerror(errno));
|
||||||
BEESCOUNT(root_open_fail);
|
BEESCOUNT(root_open_fail);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@@ -28,18 +28,18 @@ BeesTracer::~BeesTracer()
|
|||||||
{
|
{
|
||||||
if (!tl_silent && exception_check()) {
|
if (!tl_silent && exception_check()) {
|
||||||
if (tl_first) {
|
if (tl_first) {
|
||||||
BEESLOGNOTICE("--- BEGIN TRACE --- exception ---");
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: --- BEGIN TRACE --- exception ---");
|
||||||
tl_first = false;
|
tl_first = false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
m_func();
|
m_func();
|
||||||
} catch (exception &e) {
|
} catch (exception &e) {
|
||||||
BEESLOGNOTICE("Nested exception: " << e.what());
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: Nested exception: " << e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
BEESLOGNOTICE("Nested exception ...");
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: Nested exception ...");
|
||||||
}
|
}
|
||||||
if (!m_next_tracer) {
|
if (!m_next_tracer) {
|
||||||
BEESLOGNOTICE("--- END TRACE --- exception ---");
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: --- END TRACE --- exception ---");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tl_next_tracer = m_next_tracer;
|
tl_next_tracer = m_next_tracer;
|
||||||
@@ -49,7 +49,7 @@ BeesTracer::~BeesTracer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeesTracer::BeesTracer(function<void()> f, bool silent) :
|
BeesTracer::BeesTracer(const function<void()> &f, bool silent) :
|
||||||
m_func(f)
|
m_func(f)
|
||||||
{
|
{
|
||||||
m_next_tracer = tl_next_tracer;
|
m_next_tracer = tl_next_tracer;
|
||||||
@@ -61,12 +61,12 @@ void
|
|||||||
BeesTracer::trace_now()
|
BeesTracer::trace_now()
|
||||||
{
|
{
|
||||||
BeesTracer *tp = tl_next_tracer;
|
BeesTracer *tp = tl_next_tracer;
|
||||||
BEESLOGNOTICE("--- BEGIN TRACE ---");
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: --- BEGIN TRACE ---");
|
||||||
while (tp) {
|
while (tp) {
|
||||||
tp->m_func();
|
tp->m_func();
|
||||||
tp = tp->m_next_tracer;
|
tp = tp->m_next_tracer;
|
||||||
}
|
}
|
||||||
BEESLOGNOTICE("--- END TRACE ---");
|
BEESLOG(BEES_TRACE_LEVEL, "TRACE: --- END TRACE ---");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@@ -572,7 +572,7 @@ BeesRangePair::grow(shared_ptr<BeesContext> ctx, bool constrained)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (first.overlaps(second)) {
|
if (first.overlaps(second)) {
|
||||||
BEESLOGTRACE("after grow, first " << first << "\n\toverlaps " << second);
|
BEESLOGDEBUG("after grow, first " << first << "\n\toverlaps " << second);
|
||||||
BEESCOUNT(bug_grow_pair_overlaps);
|
BEESCOUNT(bug_grow_pair_overlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,7 +674,7 @@ BeesAddress::magic_check(uint64_t flags)
|
|||||||
static const unsigned recognized_flags = compressed_flags | delalloc_flags | ignore_flags | unusable_flags;
|
static const unsigned recognized_flags = compressed_flags | delalloc_flags | ignore_flags | unusable_flags;
|
||||||
|
|
||||||
if (flags & ~recognized_flags) {
|
if (flags & ~recognized_flags) {
|
||||||
BEESLOGTRACE("Unrecognized flags in " << fiemap_extent_flags_ntoa(flags));
|
BEESLOGNOTICE("Unrecognized flags in " << fiemap_extent_flags_ntoa(flags));
|
||||||
m_addr = UNUSABLE;
|
m_addr = UNUSABLE;
|
||||||
// maybe we throw here?
|
// maybe we throw here?
|
||||||
BEESCOUNT(addr_unrecognized);
|
BEESCOUNT(addr_unrecognized);
|
||||||
|
91
src/bees.cc
91
src/bees.cc
@@ -4,6 +4,7 @@
|
|||||||
#include "crucible/process.h"
|
#include "crucible/process.h"
|
||||||
#include "crucible/string.h"
|
#include "crucible/string.h"
|
||||||
#include "crucible/task.h"
|
#include "crucible/task.h"
|
||||||
|
#include "crucible/uname.h"
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -11,17 +12,19 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// PRIx64
|
// PRIx64
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <sched.h>
|
|
||||||
#include <sys/fanotify.h>
|
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
// statfs
|
||||||
|
#include <linux/magic.h>
|
||||||
|
#include <sys/statfs.h>
|
||||||
|
|
||||||
// setrlimit
|
// setrlimit
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
@@ -391,6 +394,73 @@ BeesStringFile::read()
|
|||||||
return read_string(fd, st.st_size);
|
return read_string(fd, st.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
bees_fsync(int const fd)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Note that when btrfs renames a temporary over an existing file,
|
||||||
|
// it flushes the temporary, so we get the right behavior if we
|
||||||
|
// just do nothing here (except when the file is first created;
|
||||||
|
// however, in that case the result is the same as if the file
|
||||||
|
// did not exist, was empty, or was filled with garbage).
|
||||||
|
//
|
||||||
|
// Kernel versions prior to 5.16 had bugs which would put ghost
|
||||||
|
// dirents in $BEESHOME if there was a crash when we called
|
||||||
|
// fsync() here.
|
||||||
|
//
|
||||||
|
// Some other filesystems will throw our data away if we don't
|
||||||
|
// call fsync, so we do need to call fsync() on those filesystems.
|
||||||
|
//
|
||||||
|
// Newer btrfs kernel versions rely on fsync() to report
|
||||||
|
// unrecoverable write errors. If we don't check the fsync()
|
||||||
|
// result, we'll lose the data when we rename(). Kernel 6.2 added
|
||||||
|
// a number of new root causes for the class of "unrecoverable
|
||||||
|
// write errors" so we need to check this now.
|
||||||
|
|
||||||
|
BEESNOTE("checking filesystem type for " << name_fd(fd));
|
||||||
|
// LSB deprecated statfs without providing a replacement that
|
||||||
|
// can fill in the f_type field.
|
||||||
|
struct statfs stf = { 0 };
|
||||||
|
DIE_IF_NON_ZERO(fstatfs(fd, &stf));
|
||||||
|
if (stf.f_type != BTRFS_SUPER_MAGIC) {
|
||||||
|
BEESLOGONCE("Using fsync on non-btrfs filesystem type " << to_hex(stf.f_type));
|
||||||
|
BEESNOTE("fsync non-btrfs " << name_fd(fd));
|
||||||
|
DIE_IF_NON_ZERO(fsync(fd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool did_uname = false;
|
||||||
|
static bool do_fsync = false;
|
||||||
|
|
||||||
|
if (!did_uname) {
|
||||||
|
Uname uname;
|
||||||
|
const string version(uname.release);
|
||||||
|
static const regex version_re(R"/(^(\d+)\.(\d+)\.)/", regex::optimize | regex::ECMAScript);
|
||||||
|
smatch m;
|
||||||
|
// Last known bug in the fsync-rename use case was fixed in kernel 5.16
|
||||||
|
static const auto min_major = 5, min_minor = 16;
|
||||||
|
if (regex_search(version, m, version_re)) {
|
||||||
|
const auto major = stoul(m[1]);
|
||||||
|
const auto minor = stoul(m[2]);
|
||||||
|
if (tie(major, minor) > tie(min_major, min_minor)) {
|
||||||
|
BEESLOGONCE("Using fsync on btrfs because kernel version is " << major << "." << minor);
|
||||||
|
do_fsync = true;
|
||||||
|
} else {
|
||||||
|
BEESLOGONCE("Not using fsync on btrfs because kernel version is " << major << "." << minor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BEESLOGONCE("Not using fsync on btrfs because can't parse kernel version '" << version << "'");
|
||||||
|
}
|
||||||
|
did_uname = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_fsync) {
|
||||||
|
BEESNOTE("fsync btrfs " << name_fd(fd));
|
||||||
|
DIE_IF_NON_ZERO(fsync(fd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BeesStringFile::write(string contents)
|
BeesStringFile::write(string contents)
|
||||||
{
|
{
|
||||||
@@ -406,19 +476,8 @@ BeesStringFile::write(string contents)
|
|||||||
Fd ofd = openat_or_die(m_dir_fd, tmpname, FLAGS_CREATE_FILE, S_IRUSR | S_IWUSR);
|
Fd ofd = openat_or_die(m_dir_fd, tmpname, FLAGS_CREATE_FILE, S_IRUSR | S_IWUSR);
|
||||||
BEESNOTE("writing " << tmpname << " in " << name_fd(m_dir_fd));
|
BEESNOTE("writing " << tmpname << " in " << name_fd(m_dir_fd));
|
||||||
write_or_die(ofd, contents);
|
write_or_die(ofd, contents);
|
||||||
#if 0
|
|
||||||
// This triggers too many btrfs bugs. I wish I was kidding.
|
|
||||||
// Forget snapshots, balance, compression, and dedupe:
|
|
||||||
// the system call you have to fear on btrfs is fsync().
|
|
||||||
// Also note that when bees renames a temporary over an
|
|
||||||
// existing file, it flushes the temporary, so we get
|
|
||||||
// the right behavior if we just do nothing here
|
|
||||||
// (except when the file is first created; however,
|
|
||||||
// in that case the result is the same as if the file
|
|
||||||
// did not exist, was empty, or was filled with garbage).
|
|
||||||
BEESNOTE("fsyncing " << tmpname << " in " << name_fd(m_dir_fd));
|
BEESNOTE("fsyncing " << tmpname << " in " << name_fd(m_dir_fd));
|
||||||
DIE_IF_NON_ZERO(fsync(ofd));
|
bees_fsync(ofd);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
BEESNOTE("renaming " << tmpname << " to " << m_name << " in FD " << name_fd(m_dir_fd));
|
BEESNOTE("renaming " << tmpname << " to " << m_name << " in FD " << name_fd(m_dir_fd));
|
||||||
BEESTRACE("renaming " << tmpname << " to " << m_name << " in FD " << name_fd(m_dir_fd));
|
BEESTRACE("renaming " << tmpname << " to " << m_name << " in FD " << name_fd(m_dir_fd));
|
||||||
@@ -682,7 +741,7 @@ bees_main(int argc, char *argv[])
|
|||||||
BEESLOGDEBUG("exception (ignored): " << s);
|
BEESLOGDEBUG("exception (ignored): " << s);
|
||||||
BEESCOUNT(exception_caught_silent);
|
BEESCOUNT(exception_caught_silent);
|
||||||
} else {
|
} else {
|
||||||
BEESLOGNOTICE("\n\n*** EXCEPTION ***\n\t" << s << "\n***\n");
|
BEESLOGNOTICE("\n\nTRACE: *** EXCEPTION ***\n\t" << s << "\n***\n");
|
||||||
BEESCOUNT(exception_caught);
|
BEESCOUNT(exception_caught);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
14
src/bees.h
14
src/bees.h
@@ -122,9 +122,9 @@ const int FLAGS_OPEN_FANOTIFY = O_RDWR | O_NOATIME | O_CLOEXEC | O_LARGEFILE;
|
|||||||
// macros ----------------------------------------
|
// macros ----------------------------------------
|
||||||
|
|
||||||
#define BEESLOG(lv,x) do { if (lv < bees_log_level) { Chatter __chatter(lv, BeesNote::get_name()); __chatter << x; } } while (0)
|
#define BEESLOG(lv,x) do { if (lv < bees_log_level) { Chatter __chatter(lv, BeesNote::get_name()); __chatter << x; } } while (0)
|
||||||
#define BEESLOGTRACE(x) do { BEESLOG(LOG_DEBUG, x); BeesTracer::trace_now(); } while (0)
|
|
||||||
|
|
||||||
#define BEESTRACE(x) BeesTracer SRSLY_WTF_C(beesTracer_, __LINE__) ([&]() { BEESLOG(LOG_ERR, x << " at " << __FILE__ << ":" << __LINE__); })
|
#define BEES_TRACE_LEVEL LOG_DEBUG
|
||||||
|
#define BEESTRACE(x) BeesTracer SRSLY_WTF_C(beesTracer_, __LINE__) ([&]() { BEESLOG(BEES_TRACE_LEVEL, "TRACE: " << x << " at " << __FILE__ << ":" << __LINE__); })
|
||||||
#define BEESTOOLONG(x) BeesTooLong SRSLY_WTF_C(beesTooLong_, __LINE__) ([&](ostream &_btl_os) { _btl_os << x; })
|
#define BEESTOOLONG(x) BeesTooLong SRSLY_WTF_C(beesTooLong_, __LINE__) ([&](ostream &_btl_os) { _btl_os << x; })
|
||||||
#define BEESNOTE(x) BeesNote SRSLY_WTF_C(beesNote_, __LINE__) ([&](ostream &_btl_os) { _btl_os << x; })
|
#define BEESNOTE(x) BeesNote SRSLY_WTF_C(beesNote_, __LINE__) ([&](ostream &_btl_os) { _btl_os << x; })
|
||||||
|
|
||||||
@@ -134,6 +134,14 @@ const int FLAGS_OPEN_FANOTIFY = O_RDWR | O_NOATIME | O_CLOEXEC | O_LARGEFILE;
|
|||||||
#define BEESLOGINFO(x) BEESLOG(LOG_INFO, x)
|
#define BEESLOGINFO(x) BEESLOG(LOG_INFO, x)
|
||||||
#define BEESLOGDEBUG(x) BEESLOG(LOG_DEBUG, x)
|
#define BEESLOGDEBUG(x) BEESLOG(LOG_DEBUG, x)
|
||||||
|
|
||||||
|
#define BEESLOGONCE(__x) do { \
|
||||||
|
static bool already_logged = false; \
|
||||||
|
if (!already_logged) { \
|
||||||
|
already_logged = true; \
|
||||||
|
BEESLOGNOTICE(__x); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
#define BEESCOUNT(stat) do { \
|
#define BEESCOUNT(stat) do { \
|
||||||
BeesStats::s_global.add_count(#stat); \
|
BeesStats::s_global.add_count(#stat); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -185,7 +193,7 @@ class BeesTracer {
|
|||||||
thread_local static bool tl_silent;
|
thread_local static bool tl_silent;
|
||||||
thread_local static bool tl_first;
|
thread_local static bool tl_first;
|
||||||
public:
|
public:
|
||||||
BeesTracer(function<void()> f, bool silent = false);
|
BeesTracer(const function<void()> &f, bool silent = false);
|
||||||
~BeesTracer();
|
~BeesTracer();
|
||||||
static void trace_now();
|
static void trace_now();
|
||||||
static bool get_silent();
|
static bool get_silent();
|
||||||
|
Reference in New Issue
Block a user