crimson: introduce rollback_obc_if_modified without an error argument

Signed-off-by: Samuel Just <sjust@redhat.com>
This commit is contained in:
Samuel Just 2024-09-20 12:56:17 -07:00
parent 24b7b4f4b5
commit 5e28a3bd3b

View File

@ -551,6 +551,7 @@ OpsExecuter::flush_changes_n_do_ops_effects(
template <class Func>
struct OpsExecuter::RollbackHelper {
void rollback_obc_if_modified();
void rollback_obc_if_modified(const std::error_code& e);
seastar::lw_shared_ptr<OpsExecuter> ox;
Func func;
@ -562,6 +563,33 @@ OpsExecuter::create_rollbacker(Func&& func) {
return {shared_from_this(), std::forward<Func>(func)};
}
template <class Func>
void OpsExecuter::RollbackHelper<Func>::rollback_obc_if_modified()
{
// Oops, an operation had failed. do_osd_ops() altogether with
// OpsExecuter already dropped the ObjectStore::Transaction if
// there was any. However, this is not enough to completely
// rollback as we gave OpsExecuter the very single copy of `obc`
// we maintain and we did it for both reading and writing.
// Now all modifications must be reverted.
//
// The conditional's purpose is to efficiently handle hot errors
// which may appear as a result of e.g. CEPH_OSD_OP_CMPXATTR or
// CEPH_OSD_OP_OMAP_CMP. These are read-like ops and clients
// typically append them before any write. If OpsExecuter hasn't
// seen any modifying operation, `obc` is supposed to be kept
// unchanged.
assert(ox);
const auto need_rollback = ox->has_seen_write();
crimson::get_logger(ceph_subsys_osd).debug(
"{}: object {} got error, need_rollback={}",
__func__,
ox->obc->get_oid(),
need_rollback);
if (need_rollback) {
func(ox->obc);
}
}
template <class Func>
void OpsExecuter::RollbackHelper<Func>::rollback_obc_if_modified(