From 327dd257d3aacc50c560a34cf6e3f61111813ba8 Mon Sep 17 00:00:00 2001 From: Samuel Just Date: Wed, 19 Oct 2016 09:56:46 -0700 Subject: [PATCH] osd/ECBackend: use an explicit backfill field on ECSubWrite Previously, we used an empty transaction to indicate when we were sending the op to a backfill peer which needs the logs, but can't run the transaction. I'd like to be able to send and empty transaction for the rollforward side effect without it causing the peer to think it missed a backfill op, so instead, use an explicit flag. Compatability is handled by interpretting an old version encoding with an empty transaction as having the backfill field filled. Signed-off-by: Samuel Just --- src/osd/ECBackend.cc | 7 ++++--- src/osd/ECMsgTypes.cc | 14 ++++++++++++-- src/osd/ECMsgTypes.h | 9 +++++++-- src/osd/PG.cc | 4 ++-- src/osd/PG.h | 2 +- src/osd/PGLog.h | 10 +++++++++- 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/osd/ECBackend.cc b/src/osd/ECBackend.cc index fe2260ae08607..8e709bc388265 100644 --- a/src/osd/ECBackend.cc +++ b/src/osd/ECBackend.cc @@ -887,7 +887,7 @@ void ECBackend::handle_sub_write( if (!op.temp_added.empty()) { add_temp_objs(op.temp_added); } - if (op.t.empty()) { + if (op.backfill) { for (set::iterator i = op.temp_removed.begin(); i != op.temp_removed.end(); ++i) { @@ -907,7 +907,7 @@ void ECBackend::handle_sub_write( op.updated_hit_set_history, op.trim_to, op.roll_forward_to, - !(op.t.empty()), + !op.backfill, localt); ReplicatedPG *_rPG = dynamic_cast(get_parent()); @@ -1915,7 +1915,8 @@ bool ECBackend::try_reads_to_commit() op->log_entries, op->updated_hit_set_history, op->temp_added, - op->temp_cleared); + op->temp_cleared, + !should_send); if (*i == get_parent()->whoami_shard()) { handle_sub_write( get_parent()->whoami_shard(), diff --git a/src/osd/ECMsgTypes.cc b/src/osd/ECMsgTypes.cc index a914f9f07c084..2223e7f91a366 100644 --- a/src/osd/ECMsgTypes.cc +++ b/src/osd/ECMsgTypes.cc @@ -16,7 +16,7 @@ void ECSubWrite::encode(bufferlist &bl) const { - ENCODE_START(3, 1, bl); + ENCODE_START(4, 1, bl); ::encode(from, bl); ::encode(tid, bl); ::encode(reqid, bl); @@ -30,12 +30,13 @@ void ECSubWrite::encode(bufferlist &bl) const ::encode(temp_removed, bl); ::encode(updated_hit_set_history, bl); ::encode(roll_forward_to, bl); + ::encode(backfill, bl); ENCODE_FINISH(bl); } void ECSubWrite::decode(bufferlist::iterator &bl) { - DECODE_START(3, bl); + DECODE_START(4, bl); ::decode(from, bl); ::decode(tid, bl); ::decode(reqid, bl); @@ -55,6 +56,12 @@ void ECSubWrite::decode(bufferlist::iterator &bl) } else { roll_forward_to = trim_to; } + if (struct_v >= 4) { + ::decode(backfill, bl); + } else { + // The old protocol used an empty transaction to indicate backfill + backfill = t.empty(); + } DECODE_FINISH(bl); } @@ -68,6 +75,8 @@ std::ostream &operator<<( << ", roll_forward_to=" << rhs.roll_forward_to; if (rhs.updated_hit_set_history) lhs << ", has_updated_hit_set_history"; + if (rhs.backfill) + lhs << ", backfill"; return lhs << ")"; } @@ -80,6 +89,7 @@ void ECSubWrite::dump(Formatter *f) const f->dump_stream("roll_forward_to") << roll_forward_to; f->dump_bool("has_updated_hit_set_history", static_cast(updated_hit_set_history)); + f->dump_bool("backfill", backfill); } void ECSubWrite::generate_test_instances(list &o) diff --git a/src/osd/ECMsgTypes.h b/src/osd/ECMsgTypes.h index 80ea35d9e4d75..d28b6efa7df22 100644 --- a/src/osd/ECMsgTypes.h +++ b/src/osd/ECMsgTypes.h @@ -34,6 +34,7 @@ struct ECSubWrite { set temp_added; set temp_removed; boost::optional updated_hit_set_history; + bool backfill = false; ECSubWrite() : tid(0) {} ECSubWrite( pg_shard_t from, @@ -48,7 +49,8 @@ struct ECSubWrite { vector log_entries, boost::optional updated_hit_set_history, const set &temp_added, - const set &temp_removed) + const set &temp_removed, + bool backfill) : from(from), tid(tid), reqid(reqid), soid(soid), stats(stats), t(t), at_version(at_version), @@ -56,7 +58,9 @@ struct ECSubWrite { log_entries(log_entries), temp_added(temp_added), temp_removed(temp_removed), - updated_hit_set_history(updated_hit_set_history) {} + updated_hit_set_history(updated_hit_set_history), + backfill(backfill) + {} void claim(ECSubWrite &other) { from = other.from; tid = other.tid; @@ -71,6 +75,7 @@ struct ECSubWrite { temp_added.swap(other.temp_added); temp_removed.swap(other.temp_removed); updated_hit_set_history = other.updated_hit_set_history; + backfill = other.backfill; } void encode(bufferlist &bl) const; void decode(bufferlist::iterator &bl); diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 030d4abce5301..7315c28b5b483 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -3012,7 +3012,7 @@ void PG::trim_peers() } } -void PG::add_log_entry(const pg_log_entry_t& e) +void PG::add_log_entry(const pg_log_entry_t& e, bool applied) { // raise last_complete only if we were previously up to date if (info.last_complete == info.last_update) @@ -3028,7 +3028,7 @@ void PG::add_log_entry(const pg_log_entry_t& e) info.last_user_version = e.user_version; // log mutation - pg_log.add(e); + pg_log.add(e, applied); dout(10) << "add_log_entry " << e << dendl; } diff --git a/src/osd/PG.h b/src/osd/PG.h index 517970cc68f26..e98e5a61bab88 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -2203,7 +2203,7 @@ public: return at_version; } - void add_log_entry(const pg_log_entry_t& e); + void add_log_entry(const pg_log_entry_t& e, bool applied); void append_log( const vector& logv, eversion_t trim_to, diff --git a/src/osd/PGLog.h b/src/osd/PGLog.h index 786dda6a29b75..eff487db2efa2 100644 --- a/src/osd/PGLog.h +++ b/src/osd/PGLog.h @@ -419,7 +419,11 @@ public: } // actors - void add(const pg_log_entry_t& e) { + void add(const pg_log_entry_t& e, bool applied = true) { + if (!applied) { + assert(get_can_rollback_to() == head); + } + // add to log log.push_back(e); @@ -449,6 +453,10 @@ public: extra_caller_ops.insert(make_pair(j->first, &(log.back()))); } } + + if (!applied) { + skip_can_rollback_to_to_head(); + } } void trim( -- 2.39.5