diff --git a/src/bees-context.cc b/src/bees-context.cc index 5f17e25..2c11ed9 100644 --- a/src/bees-context.cc +++ b/src/bees-context.cc @@ -243,25 +243,36 @@ BeesContext::dedup(const BeesRangePair &brp_in) BEESNOTE("waiting to dedup " << brp); const auto lock = MultiLocker::get_lock("dedupe"); - Timer dedup_timer; - BEESLOGINFO("dedup: src " << pretty(brp.first.size()) << " [" << to_hex(brp.first.begin()) << ".." << to_hex(brp.first.end()) << "] {" << first_addr << "} " << name_fd(brp.first.fd()) << "\n" << " dst " << pretty(brp.second.size()) << " [" << to_hex(brp.second.begin()) << ".." << to_hex(brp.second.end()) << "] {" << second_addr << "} " << name_fd(brp.second.fd())); BEESNOTE("dedup: src " << pretty(brp.first.size()) << " [" << to_hex(brp.first.begin()) << ".." << to_hex(brp.first.end()) << "] {" << first_addr << "} " << name_fd(brp.first.fd()) << "\n" << " dst " << pretty(brp.second.size()) << " [" << to_hex(brp.second.begin()) << ".." << to_hex(brp.second.end()) << "] {" << second_addr << "} " << name_fd(brp.second.fd())); - const bool rv = btrfs_extent_same(brp.first.fd(), brp.first.begin(), brp.first.size(), brp.second.fd(), brp.second.begin()); - BEESCOUNTADD(dedup_ms, dedup_timer.age() * 1000); + while (true) { + try { + Timer dedup_timer; + const bool rv = btrfs_extent_same(brp.first.fd(), brp.first.begin(), brp.first.size(), brp.second.fd(), brp.second.begin()); + BEESCOUNTADD(dedup_ms, dedup_timer.age() * 1000); - if (rv) { - BEESCOUNT(dedup_hit); - BEESCOUNTADD(dedup_bytes, brp.first.size()); - } else { - BEESCOUNT(dedup_miss); - BEESLOGWARN("NO Dedup! " << brp); + if (rv) { + BEESCOUNT(dedup_hit); + BEESCOUNTADD(dedup_bytes, brp.first.size()); + } else { + BEESCOUNT(dedup_miss); + BEESLOGWARN("NO Dedup! " << brp); + } + + return rv; + } catch (const std::system_error &e) { + if (e.code().value() == EAGAIN) { + BEESNOTE("dedup waiting for btrfs send on " << brp.second); + BEESLOGDEBUG("dedup waiting for btrfs send on " << brp.second); + roots()->wait_for_transid(1); + } else { + throw; + } + } } - - return rv; } BeesRangePair diff --git a/src/bees-roots.cc b/src/bees-roots.cc index 595993c..19078c0 100644 --- a/src/bees-roots.cc +++ b/src/bees-roots.cc @@ -1479,6 +1479,15 @@ BeesRoots::clear_caches() m_ctx->resolve_cache_clear(); } +void +BeesRoots::wait_for_transid(const uint64_t count) +{ + const auto now_transid = transid_max_nocache(); + const auto target_transid = now_transid + count; + BEESLOGDEBUG("Waiting for transid " << target_transid << ", current transid is " << now_transid); + m_transid_re.wait_until(target_transid); +} + void BeesRoots::crawl_thread() { diff --git a/src/bees.h b/src/bees.h index 11c0c72..a280860 100644 --- a/src/bees.h +++ b/src/bees.h @@ -552,6 +552,8 @@ class BeesRoots : public enable_shared_from_this { BeesThread m_writeback_thread; bool m_workaround_btrfs_send = false; + RateEstimator m_transid_re; + shared_ptr m_scanner; mutex m_tmpfiles_mutex; @@ -613,6 +615,8 @@ public: uint64_t transid_min(); uint64_t transid_max(); + + void wait_for_transid(const uint64_t count); }; struct BeesHash {