pg_info_t &oinfo,
const pg_log_t &olog,
pg_missing_t& omissing,
- pg_shard_t from) const
+ pg_shard_t from,
+ bool ec_optimizations_enabled) const
{
dout(10) << "proc_replica_log for osd." << from << ": "
<< oinfo << " " << olog << " " << omissing << dendl;
olog.get_can_rollback_to(),
omissing,
0,
+ ec_optimizations_enabled,
this);
if (lu < oinfo.last_update) {
*/
void PGLog::rewind_divergent_log(eversion_t newhead,
pg_info_t &info, LogEntryHandler *rollbacker,
- bool &dirty_info, bool &dirty_big_info)
+ bool &dirty_info, bool &dirty_big_info,
+ bool ec_optimizations_enabled)
{
dout(10) << "rewind_divergent_log truncate divergent future " <<
newhead << dendl;
original_crt,
missing,
rollbacker,
+ ec_optimizations_enabled,
this);
dirty_info = true;
// do we have divergent entries to throw out?
if (olog.head < log.head) {
- rewind_divergent_log(olog.head, info, rollbacker, dirty_info, dirty_big_info);
+ rewind_divergent_log(olog.head, info, rollbacker,
+ dirty_info, dirty_big_info, ec_optimizations_enabled);
changed = true;
}
original_crt,
missing,
rollbacker,
+ ec_optimizations_enabled,
this);
info.last_update = log.head = olog.head;
void proc_replica_log(pg_info_t &oinfo,
const pg_log_t &olog,
- pg_missing_t& omissing, pg_shard_t from) const;
+ pg_missing_t& omissing, pg_shard_t from,
+ bool ec_optimizations_enabled) const;
void set_missing_may_contain_deletes() {
missing.may_include_deletes = true;
eversion_t olog_can_rollback_to, ///< [in] rollback boundary of input InedexedLog
missing_type &missing, ///< [in,out] missing to adjust, use
LogEntryHandler *rollbacker, ///< [in] optional rollbacker object
+ bool ec_optimizations_enabled, ///< [in] relax asserts for allow_ec_optimzations pools
const DoutPrefixProvider *dpp ///< [in] logging provider
) {
ldpp_dout(dpp, 20) << __func__ << ": merging hoid " << hoid
// in increasing order of version
ceph_assert(i->version > last);
// prior_version correct (unless it is an ERROR entry)
- ceph_assert(i->prior_version == last || i->is_error());
+ if (ec_optimizations_enabled) {
+ // With partial writes prior_verson may be > last because of
+ // skipped log entries
+ ceph_assert(i->prior_version >= last || i->is_error());
+ } else {
+ ceph_assert(i->prior_version == last || i->is_error());
+ }
}
if (i->is_error()) {
ldpp_dout(dpp, 20) << __func__ << ": ignoring " << *i << dendl;
// ensure missing has been updated appropriately
if (objiter->second->is_update() ||
(missing.may_include_deletes && objiter->second->is_delete())) {
- ceph_assert(missing.is_missing(hoid) &&
- missing.get_items().at(hoid).need == objiter->second->version);
+ if (ec_optimizations_enabled) {
+ // relax the assert for partial writes - missing may be newer than the
+ // most recent log entry
+ ceph_assert(missing.is_missing(hoid) &&
+ missing.get_items().at(hoid).need >= objiter->second->version);
+ } else {
+ ceph_assert(missing.is_missing(hoid) &&
+ missing.get_items().at(hoid).need == objiter->second->version);
+ }
} else {
ceph_assert(!missing.is_missing(hoid));
}
eversion_t olog_can_rollback_to, ///< [in] rollback boundary of input IndexedLog
missing_type &omissing, ///< [in,out] missing to adjust, use
LogEntryHandler *rollbacker, ///< [in] optional rollbacker object
+ bool ec_optimizations_enabled, ///< [in] relax asserts for allow_ec_optimzations pools
const DoutPrefixProvider *dpp ///< [in] logging provider
) {
std::map<hobject_t, mempool::osd_pglog::list<pg_log_entry_t> > split;
olog_can_rollback_to,
omissing,
rollbacker,
+ ec_optimizations_enabled,
dpp);
}
}
log.get_can_rollback_to(),
missing,
rollbacker,
+ false, // not allow_ec_optimizations pool
this);
}
pg_info_t &info,
LogEntryHandler *rollbacker,
bool &dirty_info,
- bool &dirty_big_info);
+ bool &dirty_big_info,
+ bool ec_optimizations_enabled);
void merge_log(pg_info_t &oinfo,
pg_log_t&& olog,
invalidate_stats = invalidate_stats || !p->is_error();
if (log) {
ldpp_dout(dpp, 20) << "update missing, append " << *p << dendl;
- log->add(*p);
+ // Skip the log entry if it is a partial write that did not involve
+ // this shard
+ if (!pool.is_nonprimary_shard(shard) || p->is_written_shard(shard)) {
+ log->add(*p);
+ }
}
if (p->soid <= last_backfill &&
!p->is_error()) {
{
PGLog::LogEntryHandlerRef rollbacker{pl->get_log_handler(t)};
pg_log.rewind_divergent_log(
- newhead, info, rollbacker.get(), dirty_info, dirty_big_info);
+ newhead, info, rollbacker.get(), dirty_info, dirty_big_info,
+ pool.info.allows_ecoptimizations());
}
psdout(10) << "proc_replica_log for osd." << from << ": "
<< oinfo << " " << olog << " " << omissing << dendl;
- pg_log.proc_replica_log(oinfo, olog, omissing, from);
+ pg_log.proc_replica_log(oinfo, olog, omissing, from, pool.info.allows_ecoptimizations());
peer_info[from] = oinfo;
update_peer_info(from, oinfo);
pg_info_t oinfo = tcase.get_divinfo();
proc_replica_log(
- oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0)));
+ oinfo, olog, omissing, pg_shard_t(1, shard_id_t(0)), false);
ceph_assert(oinfo.last_update >= log.tail);
TestHandler h(remove_snap);
rewind_divergent_log(newhead, info, &h,
- dirty_info, dirty_big_info);
+ dirty_info, dirty_big_info, false);
EXPECT_TRUE(log.objects.count(divergent));
EXPECT_TRUE(missing.is_missing(divergent_object));
TestHandler h(remove_snap);
rewind_divergent_log(newhead, info, &h,
- dirty_info, dirty_big_info);
+ dirty_info, dirty_big_info, false);
EXPECT_TRUE(missing.is_missing(divergent_object));
EXPECT_EQ(0U, log.objects.count(divergent_object));
TestHandler h(remove_snap);
roll_forward_to(eversion_t(1, 6), &info, &h);
rewind_divergent_log(eversion_t(1, 5), info, &h,
- dirty_info, dirty_big_info);
+ dirty_info, dirty_big_info, false);
pg_log_t log;
reset_backfill_claim_log(log, &info, &h);
}
EXPECT_EQ(last_complete, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_FALSE(omissing.have_missing());
EXPECT_EQ(last_update, oinfo.last_update);
EXPECT_EQ(olog.head, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_FALSE(omissing.have_missing());
}
EXPECT_EQ(olog.head, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_TRUE(omissing.have_missing());
EXPECT_TRUE(omissing.is_missing(divergent_object));
EXPECT_EQ(olog.head, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_TRUE(omissing.have_missing());
EXPECT_TRUE(omissing.is_missing(divergent_object));
EXPECT_EQ(olog.head, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_TRUE(omissing.have_missing());
EXPECT_TRUE(omissing.is_missing(divergent_object));
EXPECT_EQ(olog.head, oinfo.last_complete);
missing.may_include_deletes = false;
- proc_replica_log(oinfo, olog, omissing, from);
+ proc_replica_log(oinfo, olog, omissing, from, false);
EXPECT_TRUE(omissing.have_missing());
EXPECT_TRUE(omissing.get_items().begin()->second.need == eversion_t(1, 1));
orig_entries, oinfo,
log.get_can_rollback_to(),
missing, &rollbacker,
- this);
+ false, this);
// No core dump
}
{
orig_entries, oinfo,
log.get_can_rollback_to(),
missing, &rollbacker,
- this);
+ false, this);
// No core dump
}
}