}
}
+OpsExecuter::rep_op_fut_t
+OpsExecuter::flush_changes_and_submit(
+ const std::vector<OSDOp>& ops,
+ SnapMapper& snap_mapper,
+ OSDriver& osdriver)
+{
+ const bool want_mutate = !txn.empty();
+ // osd_op_params are instantiated by every wr-like operation.
+ assert(osd_op_params || !want_mutate);
+ assert(obc);
+
+ auto submitted = interruptor::now();
+ auto all_completed = interruptor::now();
+
+ if (cloning_ctx) {
+ ceph_assert(want_mutate);
+ }
+
+ apply_stats();
+ if (want_mutate) {
+ auto log_entries = flush_clone_metadata(
+ prepare_transaction(ops),
+ snap_mapper,
+ osdriver,
+ txn);
+
+ if (auto log_rit = log_entries.rbegin(); log_rit != log_entries.rend()) {
+ ceph_assert(log_rit->version == osd_op_params->at_version);
+ }
+
+ pg->mutate_object(obc, txn, *osd_op_params);
+ /*
+ * This works around the gcc bug causing the generated code to incorrectly
+ * execute unconditionally before the predicate.
+ *
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101244
+ */
+ auto clone_obc = cloning_ctx
+ ? std::move(cloning_ctx->clone_obc)
+ : nullptr;
+ auto [_submitted, _all_completed] = co_await pg->submit_transaction(
+ std::move(obc),
+ std::move(clone_obc),
+ std::move(txn),
+ std::move(*osd_op_params),
+ std::move(log_entries)
+ );
+
+ submitted = std::move(_submitted);
+ all_completed = std::move(_all_completed);
+ }
+
+ if (op_effects.size()) [[unlikely]] {
+ // need extra ref pg due to apply_stats() which can be executed after
+ // informing snap mapper
+ all_completed =
+ std::move(all_completed).then_interruptible([this, pg=this->pg] {
+ // let's do the cleaning of `op_effects` in destructor
+ return interruptor::do_for_each(op_effects,
+ [pg=std::move(pg)](auto& op_effect) {
+ return op_effect->execute(pg);
+ });
+ });
+ }
+
+ co_return std::make_tuple(
+ std::move(submitted),
+ std::move(all_completed));
+}
+
void OpsExecuter::fill_op_params(OpsExecuter::modified_by m)
{
osd_op_params.emplace();
std::tuple<interruptible_future<>, interruptible_future<>>;
using rep_op_fut_t =
interruptible_future<rep_op_fut_tuple>;
- template <typename MutFunc>
rep_op_fut_t flush_changes_and_submit(
const std::vector<OSDOp>& ops,
SnapMapper& snap_mapper,
- OSDriver& osdriver,
- MutFunc mut_func) &&;
+ OSDriver& osdriver);
std::vector<pg_log_entry_t> prepare_transaction(
const std::vector<OSDOp>& ops);
void fill_op_params(modified_by m);
return std::forward<MainFunc>(main_func)(ctx_ref);
}
-template <typename MutFunc>
-OpsExecuter::rep_op_fut_t
-OpsExecuter::flush_changes_and_submit(
- const std::vector<OSDOp>& ops,
- SnapMapper& snap_mapper,
- OSDriver& osdriver,
- MutFunc mut_func) &&
-{
- const bool want_mutate = !txn.empty();
- // osd_op_params are instantiated by every wr-like operation.
- assert(osd_op_params || !want_mutate);
- assert(obc);
-
- auto submitted = interruptor::now();
- auto all_completed = interruptor::now();
-
- if (cloning_ctx) {
- ceph_assert(want_mutate);
- }
-
- apply_stats();
- if (want_mutate) {
- auto log_entries = flush_clone_metadata(
- prepare_transaction(ops),
- snap_mapper,
- osdriver,
- txn);
-
- if (auto log_rit = log_entries.rbegin(); log_rit != log_entries.rend()) {
- ceph_assert(log_rit->version == osd_op_params->at_version);
- }
-
- /*
- * This works around the gcc bug causing the generated code to incorrectly
- * execute unconditionally before the predicate.
- *
- * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101244
- */
- auto clone_obc = cloning_ctx
- ? std::move(cloning_ctx->clone_obc)
- : nullptr;
- auto [_submitted, _all_completed] = co_await mut_func(
- std::move(txn),
- std::move(obc),
- std::move(*osd_op_params),
- std::move(log_entries),
- std::move(clone_obc));
-
- submitted = std::move(_submitted);
- all_completed = std::move(_all_completed);
- }
-
- if (op_effects.size()) [[unlikely]] {
- // need extra ref pg due to apply_stats() which can be executed after
- // informing snap mapper
- all_completed =
- std::move(all_completed).then_interruptible([this, pg=this->pg] {
- // let's do the cleaning of `op_effects` in destructor
- return interruptor::do_for_each(op_effects,
- [pg=std::move(pg)](auto& op_effect) {
- return op_effect->execute(pg);
- });
- });
- }
-
- co_return std::make_tuple(
- std::move(submitted),
- std::move(all_completed));
-}
-
template <class Func>
struct OpsExecuter::RollbackHelper {
void rollback_obc_if_modified();
).flush_changes_and_submit(
ops,
snap_mapper,
- osdriver,
- [FNAME, this](auto&& txn,
- auto&& obc,
- auto&& osd_op_p,
- auto&& log_entries,
- auto&& new_clone) {
- DEBUGDPP("object {} submitting txn", *this, obc->get_oid());
- mutate_object(obc, txn, osd_op_p);
- return submit_transaction(
- std::move(obc),
- std::move(new_clone),
- std::move(txn),
- std::move(osd_op_p),
- std::move(log_entries));
- });
-
+ osdriver
+ );
co_return std::make_tuple(
std::move(submitted).then_interruptible([unlocker=std::move(unlocker)] {}),
std::move(completed));
struct do_osd_ops_params_t;
interruptible_future<MURef<MOSDOpReply>> do_pg_ops(Ref<MOSDOp> m);
+
+public:
interruptible_future<
std::tuple<interruptible_future<>, interruptible_future<>>>
submit_transaction(
ceph::os::Transaction&& txn,
osd_op_params_t&& oop,
std::vector<pg_log_entry_t>&& log_entries);
+
+private:
interruptible_future<> repair_object(
const hobject_t& oid,
eversion_t& v);
const hobject_t &obj,
const eversion_t &v,
const std::vector<pg_shard_t> &peers);
+public:
void mutate_object(
ObjectContextRef& obc,
ceph::os::Transaction& txn,
osd_op_params_t& osd_op_p);
+private:
bool can_discard_replica_op(const Message& m, epoch_t m_map_epoch) const;
bool can_discard_op(const MOSDOp& m) const;
void context_registry_on_change();