From 66e9cc4eb583f045bee1521ee0f66d5609aac9fe Mon Sep 17 00:00:00 2001 From: Matan Breizman Date: Thu, 20 Oct 2022 09:08:44 +0000 Subject: [PATCH] crimson/osd: support snapshot rollbacks Signed-off-by: Matan Breizman --- src/crimson/osd/ops_executer.cc | 5 +- src/crimson/osd/pg_backend.cc | 94 +++++++++++++++++++-------------- src/crimson/osd/pg_backend.h | 6 ++- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/src/crimson/osd/ops_executer.cc b/src/crimson/osd/ops_executer.cc index 2e1fdd57d3fb3..fcb56aeeddc2d 100644 --- a/src/crimson/osd/ops_executer.cc +++ b/src/crimson/osd/ops_executer.cc @@ -636,9 +636,10 @@ OpsExecuter::do_execute_op(OSDOp& osd_op) return backend.writefull(os, osd_op, txn, *osd_op_params, delta_stats); }); case CEPH_OSD_OP_ROLLBACK: - return do_write_op([this, &ss=obc->get_ro_ss(), + return do_write_op([this, &head=obc, &osd_op](auto& backend, auto& os, auto& txn) { - return backend.rollback(ss, os, osd_op, txn, *osd_op_params, delta_stats); + return backend.rollback(os, osd_op, txn, *osd_op_params, delta_stats, + head, pg->obc_loader); }); case CEPH_OSD_OP_APPEND: return do_write_op([this, &osd_op](auto& backend, auto& os, auto& txn) { diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc index cf76ee80759db..a62af299fca1c 100644 --- a/src/crimson/osd/pg_backend.cc +++ b/src/crimson/osd/pg_backend.cc @@ -22,6 +22,7 @@ #include "crimson/os/futurized_collection.h" #include "crimson/os/futurized_store.h" #include "crimson/osd/osd_operation.h" +#include "crimson/osd/object_context_loader.h" #include "replicated_backend.h" #include "replicated_recovery_backend.h" #include "ec_backend.h" @@ -766,53 +767,64 @@ PGBackend::write_iertr::future<> PGBackend::writefull( op.flags); } -using mocked_load_clone_obc_ertr = crimson::errorator< - crimson::ct_error::enoent, - crimson::ct_error::object_corrupted>; -using mocked_lock_clone_obc_iertr = - ::crimson::interruptible::interruptible_errorator< - ::crimson::osd::IOInterruptCondition, - mocked_load_clone_obc_ertr>; - -static mocked_lock_clone_obc_iertr::future -mocked_load_clone_obc(const auto& coid) -{ - return crimson::ct_error::enoent::make(); -} - -static auto head2clone(const hobject_t& hoid) -{ - // TODO: transform hoid into coid - return hoid; -} - PGBackend::rollback_iertr::future<> PGBackend::rollback( - const SnapSet &ss, ObjectState& os, const OSDOp& osd_op, ceph::os::Transaction& txn, osd_op_params_t& osd_op_params, - object_stat_sum_t& delta_stats) + object_stat_sum_t& delta_stats, + crimson::osd::ObjectContextRef head, + crimson::osd::ObjectContextLoader& obc_loader) { + const ceph_osd_op& op = osd_op.op; + snapid_t snapid = (uint64_t)op.snap.snapid; assert(os.oi.soid.is_head()); logger().debug("{} deleting {} and rolling back to old snap {}", - __func__, os.oi.soid, osd_op.op.snap.snapid); - return mocked_load_clone_obc( - head2clone(os.oi.soid) - ).safe_then_interruptible([](auto clone_obc) { - // TODO: implement me! - static_cast(clone_obc); - return remove_iertr::now(); - }, crimson::ct_error::enoent::handle([this, &os, &txn, &delta_stats] { - // there's no snapshot here, or there's no object. - // if there's no snapshot, we delete the object; otherwise, do nothing. - logger().debug("rollback: deleting head on {}" - " because got ENOENT|whiteout on obc lookup", - os.oi.soid); - return remove(os, txn, delta_stats, true /*whiteout*/); - }), mocked_load_clone_obc_ertr::assert_all{ - "unexpected error code in rollback" - }); + __func__, os.oi.soid ,snapid); + hobject_t target_coid = os.oi.soid; + target_coid.snap = snapid; + return obc_loader.with_clone_obc_only( + head, target_coid, + [this, &os, &txn, &delta_stats, &osd_op_params] + (auto clone_obc) { + logger().debug("PGBackend::rollback: loaded clone_obc: {}", + clone_obc->obs.oi.soid); + // 1) Delete current head + if (os.exists) { + txn.remove(coll->get_cid(), ghobject_t{os.oi.soid, + ghobject_t::NO_GEN, shard}); + } + // 2) Clone correct snapshot into head + txn.clone(coll->get_cid(), ghobject_t{clone_obc->obs.oi.soid}, + ghobject_t{os.oi.soid}); + // Copy clone obc.os.oi to os.oi + os.oi.clear_flag(object_info_t::FLAG_WHITEOUT); + os.oi.copy_user_bits(clone_obc->obs.oi); + delta_stats.num_bytes -= os.oi.size; + delta_stats.num_bytes += clone_obc->obs.oi.size; + osd_op_params.clean_regions.mark_data_region_dirty(0, + std::max(os.oi.size, clone_obc->obs.oi.size)); + osd_op_params.clean_regions.mark_omap_dirty(); + // TODO: 3) Calculate clone_overlaps by following overlaps + // forward from rollback snapshot + return rollback_iertr::now(); + }).safe_then_interruptible([] { + logger().debug("PGBackend::rollback succefully"); + return rollback_iertr::now(); + },// there's no snapshot here, or there's no object. + // if there's no snapshot, we delete the object; + // otherwise, do nothing. + crimson::ct_error::enoent::handle( + [this, &os, &snapid, &txn, &delta_stats] { + logger().debug("PGBackend::rollback: deleting head on {}" + " with snap_id of {}" + " because got ENOENT|whiteout on obc lookup", + os.oi.soid, snapid); + return remove(os, txn, delta_stats, false); + }), + rollback_ertr::pass_further{}, + crimson::ct_error::assert_all{"unexpected error in rollback"} + ); } PGBackend::append_ierrorator::future<> PGBackend::append( @@ -949,6 +961,10 @@ PGBackend::remove(ObjectState& os, ceph::os::Transaction& txn, return crimson::ct_error::enoent::make(); } + if (!os.exists) { + logger().debug("{} {} does not exist",__func__, os.oi.soid); + return seastar::now(); + } if (whiteout && os.oi.is_whiteout()) { logger().debug("{} whiteout set on {} ",__func__, os.oi.soid); return seastar::now(); diff --git a/src/crimson/osd/pg_backend.h b/src/crimson/osd/pg_backend.h index 7000a402e8fa5..505ee7736a7f9 100644 --- a/src/crimson/osd/pg_backend.h +++ b/src/crimson/osd/pg_backend.h @@ -31,6 +31,7 @@ namespace ceph::os { namespace crimson::osd { class ShardServices; class PG; + class ObjectContextLoader; } class PGBackend @@ -193,12 +194,13 @@ public: ::crimson::osd::IOInterruptCondition, rollback_ertr>; rollback_iertr::future<> rollback( - const SnapSet &ss, ObjectState& os, const OSDOp& osd_op, ceph::os::Transaction& txn, osd_op_params_t& osd_op_params, - object_stat_sum_t& delta_stats); + object_stat_sum_t& delta_stats, + crimson::osd::ObjectContextRef head, + crimson::osd::ObjectContextLoader& obc_loader); write_iertr::future<> truncate( ObjectState& os, const OSDOp& osd_op, -- 2.39.5