map<hobject_t, ECUtil::shard_extent_map_t> *written,
shard_id_map<ObjectStore::Transaction> *transactions,
DoutPrefixProvider *dpp,
- const OSDMapRef &osdmap) final {
+ const OSDMapRef &osdmap,
+ bool& first_write_in_interval) final {
ceph_assert(t);
ECTransaction::generate_transactions(
t.get(),
&temp_added,
&temp_cleared,
dpp,
- osdmap);
+ osdmap,
+ first_write_in_interval);
}
bool skip_transaction(
&written,
&trans,
get_parent()->get_dpp(),
- get_osdmap());
+ get_osdmap(),
+ first_write_in_interval);
dout(20) << __func__ << ": written: " << written << ", op: " << op << dendl;
map<hobject_t, ECUtil::shard_extent_map_t> *written,
shard_id_map<ObjectStore::Transaction> *transactions,
DoutPrefixProvider *dpp,
- const OSDMapRef &osdmap
+ const OSDMapRef &osdmap,
+ bool &first_write_in_interval
) override {
// NOP, as -- in contrast to ECClassicalOp -- there is no
// transaction involved
oid_to_version.clear();
waiting_commit.clear();
next_write_all_shards = false;
+ first_write_in_interval = true;
}
void ECCommon::RMWPipeline::on_change2() {
std::map<hobject_t, ECUtil::shard_extent_map_t> *written,
shard_id_map<ceph::os::Transaction> *transactions,
DoutPrefixProvider *dpp,
- const OSDMapRef &osdmap) = 0;
+ const OSDMapRef &osdmap,
+ bool &first_write_in_interval) = 0;
virtual bool skip_transaction(
std::set<shard_id_t> &pending_roll_forward,
uint64_t ec_pdw_write_mode;
bool next_write_all_shards = false;
+ // Set by on_change, forces first write in each interval to be
+ // a full write to avoid PWLC spanning intervals. Fixes
+ // https://tracker.ceph.com/issues/73891
+ bool first_write_in_interval;
+
RMWPipeline(CephContext *cct,
ceph::ErasureCodeInterfaceRef ec_impl,
const ECUtil::stripe_info_t &sinfo,
PGTransaction::ObjectOperation &op,
WritePlanObj &plan,
DoutPrefixProvider *dpp,
- pg_log_entry_t *entry)
+ pg_log_entry_t *entry,
+ bool &first_write_in_interval)
: t(t),
ec_impl(ec_impl),
pgid(pgid),
}
}
- if (size_change || clear_whiteout) {
+ if (size_change || clear_whiteout || first_write_in_interval) {
all_shards_written();
+ first_write_in_interval = false;
} else {
// All primary shards must always be written, regardless of the write plan.
shards_written(sinfo.get_parity_shards());
set<hobject_t> *temp_added,
set<hobject_t> *temp_removed,
DoutPrefixProvider *dpp,
- const OSDMapRef &osdmap) {
+ const OSDMapRef &osdmap,
+ bool &first_write_in_interval) {
ceph_assert(written_map);
ceph_assert(transactions);
ceph_assert(temp_added);
ceph_assert(plan.hoid == oid);
Generate generate(t, ec_impl, pgid, sinfo, partial_extents, written_map,
- *transactions, osdmap, oid, op, plan, dpp, entry);
+ *transactions, osdmap, oid, op, plan, dpp, entry, first_write_in_interval);
plans.plans.pop_front();
});
const hobject_t &oid, PGTransaction::ObjectOperation &op,
WritePlanObj &plan,
DoutPrefixProvider *dpp,
- pg_log_entry_t *entry);
+ pg_log_entry_t *entry,
+ bool &first_write_in_interval);
};
void generate_transactions(
std::set<hobject_t> *temp_added,
std::set<hobject_t> *temp_removed,
DoutPrefixProvider *dpp,
- const OSDMapRef &osdmap
+ const OSDMapRef &osdmap,
+ bool &first_write_in_interval
);
}