diff --git a/src/bees-context.cc b/src/bees-context.cc index 51d6b87..32f83ea 100644 --- a/src/bees-context.cc +++ b/src/bees-context.cc @@ -773,11 +773,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(&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 BeesContext::resolve_addr_uncached(BeesAddress addr) { THROW_CHECK1(invalid_argument, addr, !addr.is_magic()); 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; // There is no performance benefit if we restrict the buffer size. diff --git a/src/bees.h b/src/bees.h index 5d4e432..0c88c31 100644 --- a/src/bees.h +++ b/src/bees.h @@ -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 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 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; @@ -716,6 +719,7 @@ class BeesContext : public enable_shared_from_this { void set_root_fd(Fd fd); BeesResolveAddrResult resolve_addr_uncached(BeesAddress addr); + void wait_for_balance(); BeesFileRange scan_one_extent(const BeesFileRange &bfr, const Extent &e); void rewrite_file_range(const BeesFileRange &bfr);