mirror of
https://github.com/Zygo/bees.git
synced 2025-08-03 14:23:29 +02:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a466ccf2f1 | ||
|
ba04fe1349 | ||
|
830df63d4c | ||
|
20c9d2ff6a | ||
|
7bbb4d14cb | ||
|
363c45b8cd | ||
|
4ec2b8ac16 | ||
|
26d31225fa | ||
|
21ae937201 | ||
|
7283126e5c | ||
|
ac53e50d3e |
@@ -13,7 +13,7 @@ namespace crucible {
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class ProgressTracker {
|
class ProgressTracker {
|
||||||
class ProgressTrackerState;
|
struct ProgressTrackerState;
|
||||||
class ProgressHolderState;
|
class ProgressHolderState;
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
@@ -20,6 +20,7 @@ CRUCIBLE_OBJS = \
|
|||||||
uuid.o \
|
uuid.o \
|
||||||
|
|
||||||
include ../makeflags
|
include ../makeflags
|
||||||
|
-include ../localconf
|
||||||
include ../Defines.mk
|
include ../Defines.mk
|
||||||
|
|
||||||
configure.h: configure.h.in
|
configure.h: configure.h.in
|
||||||
|
@@ -124,6 +124,7 @@ namespace crucible {
|
|||||||
} else if (!chatter_names->empty()) {
|
} else if (!chatter_names->empty()) {
|
||||||
cerr << "CRUCIBLE_CHATTER does not list '" << m_file << "' or '" << m_pretty_function << "'" << endl;
|
cerr << "CRUCIBLE_CHATTER does not list '" << m_file << "' or '" << m_pretty_function << "'" << endl;
|
||||||
}
|
}
|
||||||
|
(void)m_line; // not implemented yet
|
||||||
// cerr << "ChatterBox " << reinterpret_cast<void*>(this) << " constructed" << endl;
|
// cerr << "ChatterBox " << reinterpret_cast<void*>(this) << " constructed" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,6 @@ namespace crucible {
|
|||||||
// fm_start, fm_length, fm_flags, m_extents
|
// fm_start, fm_length, fm_flags, m_extents
|
||||||
// fe_logical, fe_physical, fe_length, fe_flags
|
// fe_logical, fe_physical, fe_length, fe_flags
|
||||||
|
|
||||||
static const off_t MAX_OFFSET = numeric_limits<off_t>::max();
|
|
||||||
static const off_t FIEMAP_BLOCK_SIZE = 4096;
|
static const off_t FIEMAP_BLOCK_SIZE = 4096;
|
||||||
|
|
||||||
static bool __ew_do_log = getenv("EXTENTWALKER_DEBUG");
|
static bool __ew_do_log = getenv("EXTENTWALKER_DEBUG");
|
||||||
|
@@ -110,9 +110,6 @@ namespace crucible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
struct ResourceHandle<Process::id, Process>;
|
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
gettid()
|
gettid()
|
||||||
{
|
{
|
||||||
|
@@ -6,6 +6,7 @@ PROGRAMS = \
|
|||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
|
|
||||||
include ../makeflags
|
include ../makeflags
|
||||||
|
-include ../localconf
|
||||||
|
|
||||||
LIBS = -lcrucible -lpthread
|
LIBS = -lcrucible -lpthread
|
||||||
LDFLAGS = -L../lib
|
LDFLAGS = -L../lib
|
||||||
|
@@ -11,17 +11,6 @@
|
|||||||
using namespace crucible;
|
using namespace crucible;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static inline
|
|
||||||
const char *
|
|
||||||
getenv_or_die(const char *name)
|
|
||||||
{
|
|
||||||
const char *rv = getenv(name);
|
|
||||||
if (!rv) {
|
|
||||||
THROW_ERROR(runtime_error, "Environment variable " << name << " not defined");
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeesFdCache::BeesFdCache()
|
BeesFdCache::BeesFdCache()
|
||||||
{
|
{
|
||||||
m_root_cache.func([&](shared_ptr<BeesContext> ctx, uint64_t root) -> Fd {
|
m_root_cache.func([&](shared_ptr<BeesContext> ctx, uint64_t root) -> Fd {
|
||||||
@@ -773,11 +762,42 @@ BeesResolveAddrResult::BeesResolveAddrResult()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BeesContext::wait_for_balance()
|
||||||
|
{
|
||||||
|
Timer balance_timer;
|
||||||
|
BEESNOTE("WORKAROUND: waiting for balance to stop");
|
||||||
|
while (true) {
|
||||||
|
btrfs_ioctl_balance_args args;
|
||||||
|
memset_zero<btrfs_ioctl_balance_args>(&args);
|
||||||
|
const int ret = ioctl(root_fd(), BTRFS_IOC_BALANCE_PROGRESS, &args);
|
||||||
|
if (ret < 0) {
|
||||||
|
// Either can't get balance status or not running, exit either way
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(args.state & BTRFS_BALANCE_STATE_RUNNING)) {
|
||||||
|
// Balance not running, doesn't matter if paused or cancelled
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BEESLOGDEBUG("WORKAROUND: Waiting " << balance_timer << "s for balance to stop");
|
||||||
|
sleep(BEES_BALANCE_POLL_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BeesResolveAddrResult
|
BeesResolveAddrResult
|
||||||
BeesContext::resolve_addr_uncached(BeesAddress addr)
|
BeesContext::resolve_addr_uncached(BeesAddress addr)
|
||||||
{
|
{
|
||||||
THROW_CHECK1(invalid_argument, addr, !addr.is_magic());
|
THROW_CHECK1(invalid_argument, addr, !addr.is_magic());
|
||||||
THROW_CHECK0(invalid_argument, !!root_fd());
|
THROW_CHECK0(invalid_argument, !!root_fd());
|
||||||
|
|
||||||
|
// Is there a bug where resolve and balance cause a crash (BUG_ON at fs/btrfs/ctree.c:1227)?
|
||||||
|
// Apparently yes, and more than one.
|
||||||
|
// Wait for the balance to finish before we run LOGICAL_INO
|
||||||
|
wait_for_balance();
|
||||||
|
|
||||||
|
// Time how long this takes
|
||||||
Timer resolve_timer;
|
Timer resolve_timer;
|
||||||
|
|
||||||
// There is no performance benefit if we restrict the buffer size.
|
// There is no performance benefit if we restrict the buffer size.
|
||||||
|
@@ -207,19 +207,15 @@ uint64_t
|
|||||||
BeesRoots::transid_max_nocache()
|
BeesRoots::transid_max_nocache()
|
||||||
{
|
{
|
||||||
uint64_t rv = 0;
|
uint64_t rv = 0;
|
||||||
uint64_t root = BTRFS_FS_TREE_OBJECTID;
|
BEESNOTE("Calculating transid_max");
|
||||||
BEESNOTE("Calculating transid_max (" << rv << " as of root " << root << ")");
|
BEESTRACE("Calculating transid_max");
|
||||||
BEESTRACE("Calculating transid_max...");
|
|
||||||
|
|
||||||
rv = btrfs_get_root_transid(root);
|
|
||||||
|
|
||||||
// XXX: Do we need any of this? Or is
|
|
||||||
// m_transid_re.update(btrfs_get_root_transid(BTRFS_FS_TREE_OBJECTID)) good enough?
|
|
||||||
|
|
||||||
|
// We look for the root of the extent tree and read its transid.
|
||||||
|
// Should run in O(1) time and be fairly reliable.
|
||||||
BtrfsIoctlSearchKey sk;
|
BtrfsIoctlSearchKey sk;
|
||||||
sk.tree_id = BTRFS_ROOT_TREE_OBJECTID;
|
sk.tree_id = BTRFS_ROOT_TREE_OBJECTID;
|
||||||
sk.min_type = sk.max_type = BTRFS_ROOT_BACKREF_KEY;
|
sk.min_type = sk.max_type = BTRFS_ROOT_ITEM_KEY;
|
||||||
sk.min_objectid = root;
|
sk.min_objectid = sk.max_objectid = BTRFS_EXTENT_TREE_OBJECTID;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
sk.nr_items = 1024;
|
sk.nr_items = 1024;
|
||||||
@@ -229,21 +225,18 @@ BeesRoots::transid_max_nocache()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are just looking for the highest transid on the filesystem.
|
||||||
|
// We don't care which object it comes from.
|
||||||
for (auto i : sk.m_result) {
|
for (auto i : sk.m_result) {
|
||||||
sk.next_min(i);
|
sk.next_min(i);
|
||||||
if (i.type == BTRFS_ROOT_BACKREF_KEY) {
|
|
||||||
if (i.transid > rv) {
|
|
||||||
BEESLOGDEBUG("transid_max root " << i.objectid << " parent " << i.offset << " transid " << i.transid);
|
|
||||||
BEESCOUNT(transid_max_miss);
|
|
||||||
}
|
|
||||||
root = i.objectid;
|
|
||||||
}
|
|
||||||
if (i.transid > rv) {
|
if (i.transid > rv) {
|
||||||
rv = i.transid;
|
rv = i.transid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_transid_re.update(rv);
|
|
||||||
|
// transid must be greater than zero, or we did something very wrong
|
||||||
|
THROW_CHECK1(runtime_error, rv, rv > 0);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,7 +973,7 @@ BeesCrawl::fetch_extents()
|
|||||||
// Lock in the old state
|
// Lock in the old state
|
||||||
set_state(old_state);
|
set_state(old_state);
|
||||||
|
|
||||||
BEESTRACE("Searching crawl sk " << static_cast<btrfs_ioctl_search_key&>(sk));
|
BEESTRACE("Searching crawl sk " << sk);
|
||||||
bool ioctl_ok = false;
|
bool ioctl_ok = false;
|
||||||
{
|
{
|
||||||
BEESNOTE("searching crawl sk " << static_cast<btrfs_ioctl_search_key&>(sk));
|
BEESNOTE("searching crawl sk " << static_cast<btrfs_ioctl_search_key&>(sk));
|
||||||
|
26
src/bees.cc
26
src/bees.cc
@@ -204,20 +204,6 @@ BeesNote::get_status()
|
|||||||
|
|
||||||
// static inline helpers ----------------------------------------
|
// static inline helpers ----------------------------------------
|
||||||
|
|
||||||
static inline
|
|
||||||
bool
|
|
||||||
bees_addr_check(uint64_t v)
|
|
||||||
{
|
|
||||||
return !(v & (1ULL << 63));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
bool
|
|
||||||
bees_addr_check(int64_t v)
|
|
||||||
{
|
|
||||||
return !(v & (1ULL << 63));
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
string
|
||||||
pretty(double d)
|
pretty(double d)
|
||||||
{
|
{
|
||||||
@@ -667,6 +653,7 @@ bees_main(int argc, char *argv[])
|
|||||||
unsigned thread_min = 0;
|
unsigned thread_min = 0;
|
||||||
double load_target = 0;
|
double load_target = 0;
|
||||||
bool workaround_btrfs_send = false;
|
bool workaround_btrfs_send = false;
|
||||||
|
BeesRoots::ScanMode root_scan_mode = BeesRoots::SCAN_MODE_ZERO;
|
||||||
|
|
||||||
// Configure getopt_long
|
// Configure getopt_long
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
@@ -735,7 +722,7 @@ bees_main(int argc, char *argv[])
|
|||||||
load_target = stod(optarg);
|
load_target = stod(optarg);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
bc->roots()->set_scan_mode(static_cast<BeesRoots::ScanMode>(stoul(optarg)));
|
root_scan_mode = static_cast<BeesRoots::ScanMode>(stoul(optarg));
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
crucible::set_relative_path("");
|
crucible::set_relative_path("");
|
||||||
@@ -806,11 +793,16 @@ bees_main(int argc, char *argv[])
|
|||||||
BEESLOGNOTICE("setting worker thread pool maximum size to " << thread_count);
|
BEESLOGNOTICE("setting worker thread pool maximum size to " << thread_count);
|
||||||
TaskMaster::set_thread_count(thread_count);
|
TaskMaster::set_thread_count(thread_count);
|
||||||
|
|
||||||
|
// Set root path
|
||||||
|
string root_path = argv[optind++];
|
||||||
|
BEESLOGNOTICE("setting root path to '" << root_path << "'");
|
||||||
|
bc->set_root_path(root_path);
|
||||||
|
|
||||||
// Workaround for btrfs send
|
// Workaround for btrfs send
|
||||||
bc->roots()->set_workaround_btrfs_send(workaround_btrfs_send);
|
bc->roots()->set_workaround_btrfs_send(workaround_btrfs_send);
|
||||||
|
|
||||||
// Create a context and start crawlers
|
// Set root scan mode
|
||||||
bc->set_root_path(argv[optind++]);
|
bc->roots()->set_scan_mode(root_scan_mode);
|
||||||
|
|
||||||
BeesThread status_thread("status", [&]() {
|
BeesThread status_thread("status", [&]() {
|
||||||
bc->dump_status();
|
bc->dump_status();
|
||||||
|
@@ -117,6 +117,9 @@ const size_t BEES_TRANSID_FACTOR = 10;
|
|||||||
// The actual limit in LOGICAL_INO seems to be 2730, but let's leave a little headroom
|
// The actual limit in LOGICAL_INO seems to be 2730, but let's leave a little headroom
|
||||||
const size_t BEES_MAX_EXTENT_REF_COUNT = 2560;
|
const size_t BEES_MAX_EXTENT_REF_COUNT = 2560;
|
||||||
|
|
||||||
|
// Wait this long for a balance to stop
|
||||||
|
const double BEES_BALANCE_POLL_INTERVAL = 60.0;
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
const int FLAGS_OPEN_COMMON = O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC | O_NOATIME | O_LARGEFILE | O_NOCTTY;
|
const int FLAGS_OPEN_COMMON = O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC | O_NOATIME | O_LARGEFILE | O_NOCTTY;
|
||||||
const int FLAGS_OPEN_DIR = FLAGS_OPEN_COMMON | O_RDONLY | O_DIRECTORY;
|
const int FLAGS_OPEN_DIR = FLAGS_OPEN_COMMON | O_RDONLY | O_DIRECTORY;
|
||||||
@@ -170,7 +173,7 @@ public:
|
|||||||
T at(string idx) const;
|
T at(string idx) const;
|
||||||
|
|
||||||
friend ostream& operator<< <>(ostream &os, const BeesStatTmpl<T> &bs);
|
friend ostream& operator<< <>(ostream &os, const BeesStatTmpl<T> &bs);
|
||||||
friend class BeesStats;
|
friend struct BeesStats;
|
||||||
};
|
};
|
||||||
|
|
||||||
using BeesRates = BeesStatTmpl<double>;
|
using BeesRates = BeesStatTmpl<double>;
|
||||||
@@ -716,6 +719,7 @@ class BeesContext : public enable_shared_from_this<BeesContext> {
|
|||||||
void set_root_fd(Fd fd);
|
void set_root_fd(Fd fd);
|
||||||
|
|
||||||
BeesResolveAddrResult resolve_addr_uncached(BeesAddress addr);
|
BeesResolveAddrResult resolve_addr_uncached(BeesAddress addr);
|
||||||
|
void wait_for_balance();
|
||||||
|
|
||||||
BeesFileRange scan_one_extent(const BeesFileRange &bfr, const Extent &e);
|
BeesFileRange scan_one_extent(const BeesFileRange &bfr, const Extent &e);
|
||||||
void rewrite_file_range(const BeesFileRange &bfr);
|
void rewrite_file_range(const BeesFileRange &bfr);
|
||||||
|
@@ -14,6 +14,7 @@ test: $(PROGRAMS:%=%.txt) Makefile
|
|||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
include ../makeflags
|
include ../makeflags
|
||||||
|
-include ../localconf
|
||||||
|
|
||||||
LIBS = -lcrucible -lpthread
|
LIBS = -lcrucible -lpthread
|
||||||
LDFLAGS = -L../lib -Wl,-rpath=$(shell realpath ../lib)
|
LDFLAGS = -L../lib -Wl,-rpath=$(shell realpath ../lib)
|
||||||
|
@@ -99,7 +99,7 @@ test_barrier(size_t count)
|
|||||||
oss << "task #" << c;
|
oss << "task #" << c;
|
||||||
Task t(
|
Task t(
|
||||||
oss.str(),
|
oss.str(),
|
||||||
[c, &task_done, &mtx, &cv, bl]() mutable {
|
[c, &task_done, &mtx, bl]() mutable {
|
||||||
// cerr << "Task #" << c << endl;
|
// cerr << "Task #" << c << endl;
|
||||||
unique_lock<mutex> lock(mtx);
|
unique_lock<mutex> lock(mtx);
|
||||||
task_done.at(c) = true;
|
task_done.at(c) = true;
|
||||||
@@ -166,8 +166,9 @@ test_exclusion(size_t count)
|
|||||||
oss << "task #" << c;
|
oss << "task #" << c;
|
||||||
Task t(
|
Task t(
|
||||||
oss.str(),
|
oss.str(),
|
||||||
[c, &only_one, &mtx, &excl, bl]() mutable {
|
[c, &only_one, &excl, bl]() mutable {
|
||||||
// cerr << "Task #" << c << endl;
|
// cerr << "Task #" << c << endl;
|
||||||
|
(void)c;
|
||||||
auto lock = excl.try_lock();
|
auto lock = excl.try_lock();
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
excl.insert_task(Task::current_task());
|
excl.insert_task(Task::current_task());
|
||||||
|
Reference in New Issue
Block a user