state = RWState::RWEXCL;
}
+ seastar::future<> lock_excl_wait() {
+ // Try immediate lock first
+ if (obc->lock.try_lock_for_excl()) {
+ state = RWState::RWEXCL;
+ return seastar::now();
+ }
+ // Otherwise, wait asynchronously
+ return obc->lock.lock_for_excl().then([this] {
+ state = RWState::RWEXCL;
+ });
+ }
+
void demote_excl_to(RWState::State lock_type) {
assert(state == RWState::RWEXCL);
switch (lock_type) {
target_state.lock_excl_sync();
}
+ seastar::future<> lock_excl_wait() {
+ return target_state.lock_excl_wait();
+ }
+
ObjectContextRef &get_obc() {
ceph_assert(!target_state.is_empty());
ceph_assert(target_state.obc->is_loaded());
pull_info.stat.num_objects_recovered++;
auto manager = pg.obc_loader.get_obc_manager(
recovery_waiter.obc);
- manager.lock_excl_sync(); /* cannot already be locked */
+ // Call lock_excl_wait if the lock is already held by load_and_lock_(head|clone)
+ // and has not been released yet.
+ co_await interruptor::make_interruptible(manager.lock_excl_wait());
co_await pg.get_recovery_handler()->on_local_recover(
push_op.soid, get_recovering(push_op.soid).pull_info->recovery_info,
false, t
auto ptiter = replica_push_targets.find(push_op.recovery_info.soid);
ceph_assert(ptiter != replica_push_targets.end());
auto manager = pg.obc_loader.get_obc_manager(ptiter->second);
- manager.lock_excl_sync(); /* cannot already be locked */
+ // Call lock_excl_wait if the lock is already held by load_and_lock_(head|clone)
+ // and has not been released yet.
+ co_await interruptor::make_interruptible(manager.lock_excl_wait());
co_await pg.get_recovery_handler()->on_local_recover(
push_op.recovery_info.soid, push_op.recovery_info,