Skip to content

Commit 166e26f

Browse files
authored
Merge pull request ceph#60803 from xxhdx1985126/wip-69027
crimson/osd/replicate_backend: add standalone delete to the push queue if the object is deleted while it's being backfilled Reviewed-by: Samuel Just <[email protected]>
2 parents 84d0301 + af1bc22 commit 166e26f

File tree

6 files changed

+64
-9
lines changed

6 files changed

+64
-9
lines changed

src/crimson/osd/backfill_state.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,17 @@ void BackfillState::enqueue_standalone_push(
677677
backfill_machine.backfill_listener.enqueue_push(obj, v, peers);
678678
}
679679

680+
void BackfillState::enqueue_standalone_delete(
681+
const hobject_t &obj,
682+
const eversion_t &v,
683+
const std::vector<pg_shard_t> &peers)
684+
{
685+
progress_tracker->enqueue_drop(obj);
686+
for (auto bt : peers) {
687+
backfill_machine.backfill_listener.enqueue_drop(bt, obj, v);
688+
}
689+
}
690+
680691
std::ostream &operator<<(std::ostream &out, const BackfillState::PGFacade &pg) {
681692
return pg.print(out);
682693
}

src/crimson/osd/backfill_state.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ struct BackfillState {
292292
const hobject_t &obj,
293293
const eversion_t &v,
294294
const std::vector<pg_shard_t> &peers);
295+
void enqueue_standalone_delete(
296+
const hobject_t &obj,
297+
const eversion_t &v,
298+
const std::vector<pg_shard_t> &peers);
299+
295300

296301
bool is_triggered() const {
297302
return backfill_machine.triggering_event() != nullptr;

src/crimson/osd/pg.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,17 @@ void PG::enqueue_push_for_backfill(
879879
backfill_state->enqueue_standalone_push(obj, v, peers);
880880
}
881881

882+
void PG::enqueue_delete_for_backfill(
883+
const hobject_t &obj,
884+
const eversion_t &v,
885+
const std::vector<pg_shard_t> &peers)
886+
{
887+
assert(recovery_handler);
888+
assert(recovery_handler->backfill_state);
889+
auto backfill_state = recovery_handler->backfill_state.get();
890+
backfill_state->enqueue_standalone_delete(obj, v, peers);
891+
}
892+
882893
PG::interruptible_future<
883894
std::tuple<PG::interruptible_future<>,
884895
PG::interruptible_future<>>>

src/crimson/osd/pg.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,11 @@ class PG : public boost::intrusive_ref_counter<
904904
const hobject_t &obj,
905905
const eversion_t &v,
906906
const std::vector<pg_shard_t> &peers);
907+
void enqueue_delete_for_backfill(
908+
const hobject_t &obj,
909+
const eversion_t &v,
910+
const std::vector<pg_shard_t> &peers);
911+
907912
bool can_discard_replica_op(const Message& m, epoch_t m_map_epoch) const;
908913
bool can_discard_op(const MOSDOp& m) const;
909914
void context_registry_on_change();

src/crimson/osd/replicated_backend.cc

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,18 @@ ReplicatedBackend::submit_transaction(
9696
bufferlist encoded_txn;
9797
encode(txn, encoded_txn);
9898

99+
bool is_delete = false;
99100
for (auto &le : log_entries) {
100101
le.mark_unrollbackable();
102+
if (le.is_delete()) {
103+
is_delete = true;
104+
}
101105
}
102106

107+
co_await pg.update_snap_map(log_entries, txn);
108+
103109
std::vector<pg_shard_t> to_push_clone;
110+
std::vector<pg_shard_t> to_push_delete;
104111
auto sends = std::make_unique<std::vector<seastar::future<>>>();
105112
for (auto &pg_shard : pg_shards) {
106113
if (pg_shard == whoami) {
@@ -115,12 +122,17 @@ ReplicatedBackend::submit_transaction(
115122
m = new_repop_msg(
116123
pg_shard, hoid, encoded_txn, osd_op_p,
117124
min_epoch, map_epoch, log_entries, false, tid);
118-
if (_new_clone && pg.is_missing_on_peer(pg_shard, hoid)) {
119-
// The head is in the push queue but hasn't been pushed yet.
120-
// We need to ensure that the newly created clone will be
121-
// pushed as well, otherwise we might skip it.
122-
// See: https://tracker.ceph.com/issues/68808
123-
to_push_clone.push_back(pg_shard);
125+
if (pg.is_missing_on_peer(pg_shard, hoid)) {
126+
if (_new_clone) {
127+
// The head is in the push queue but hasn't been pushed yet.
128+
// We need to ensure that the newly created clone will be
129+
// pushed as well, otherwise we might skip it.
130+
// See: https://tracker.ceph.com/issues/68808
131+
to_push_clone.push_back(pg_shard);
132+
}
133+
if (is_delete) {
134+
to_push_delete.push_back(pg_shard);
135+
}
124136
}
125137
}
126138
pending_txn->second.acked_peers.push_back({pg_shard, eversion_t{}});
@@ -130,8 +142,6 @@ ReplicatedBackend::submit_transaction(
130142
pg_shard.osd, std::move(m), map_epoch));
131143
}
132144

133-
co_await pg.update_snap_map(log_entries, txn);
134-
135145
pg.log_operation(
136146
std::move(log_entries),
137147
osd_op_p.pg_trim_to,
@@ -157,7 +167,8 @@ ReplicatedBackend::submit_transaction(
157167
return seastar::now();
158168
}
159169
return peers->all_committed.get_shared_future();
160-
}).then_interruptible([pending_txn, this, _new_clone,
170+
}).then_interruptible([pending_txn, this, _new_clone, &hoid,
171+
to_push_delete=std::move(to_push_delete),
161172
to_push_clone=std::move(to_push_clone)] {
162173
auto acked_peers = std::move(pending_txn->second.acked_peers);
163174
pending_trans.erase(pending_txn);
@@ -167,6 +178,9 @@ ReplicatedBackend::submit_transaction(
167178
_new_clone->obs.oi.version,
168179
to_push_clone);
169180
}
181+
if (!to_push_delete.empty()) {
182+
pg.enqueue_delete_for_backfill(hoid, {}, to_push_delete);
183+
}
170184
return seastar::make_ready_future<
171185
crimson::osd::acked_peers_t>(std::move(acked_peers));
172186
});

src/crimson/osd/replicated_recovery_backend.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ ReplicatedRecoveryBackend::recover_object(
3535
logger().debug("recover_object: loading obc: {}", soid);
3636
return pg.obc_loader.with_obc<RWState::RWREAD>(soid,
3737
[this, soid, need](auto head, auto obc) {
38+
if (!obc->obs.exists) {
39+
// XXX: this recovery must be triggered by backfills and the corresponding
40+
// object must have been deleted by some client request after the object
41+
// is enqueued for push but before the lock is acquired by the recovery.
42+
//
43+
// Abort the recovery in this case, a "recover_delete" must have been
44+
// added for this object by the client request that deleted it.
45+
return interruptor::now();
46+
}
3847
logger().debug("recover_object: loaded obc: {}", obc->obs.oi.soid);
3948
auto& recovery_waiter = get_recovering(soid);
4049
recovery_waiter.obc = obc;

0 commit comments

Comments
 (0)