Skip to content

Commit 7150576

Browse files
authored
Merge pull request ceph#62535 from Matan-B/wip-matanb-crimson-replicated-missing
osd/../client_request: Fix clone replicated reads Reviewed-by: Samuel Just <[email protected]>
2 parents 46ba365 + 480b7c6 commit 7150576

File tree

7 files changed

+56
-4
lines changed

7 files changed

+56
-4
lines changed

src/crimson/osd/ops_executer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,7 @@ pg_log_entry_t OpsExecuter::prepare_head_update(
903903
{
904904
LOG_PREFIX(OpsExecuter::prepare_head_update);
905905
assert(obc->obs.oi.soid.snap >= CEPH_MAXSNAP);
906+
assert(obc->obs.oi.soid.is_head());
906907

907908
update_clone_overlap();
908909
if (cloning_ctx) {

src/crimson/osd/osd_operations/client_request.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,16 @@ ClientRequest::interruptible_future<> ClientRequest::with_pg_process_interruptib
197197
}
198198

199199
pg.get_perf_logger().inc(l_osd_replica_read);
200-
if (pg.is_unreadable_object(m->get_hobj())) {
201-
DEBUGDPP("{}.{}: {} missing on replica, bouncing to primary",
202-
pg, *this, this_instance_id, m->get_hobj());
200+
if (pg.is_missing_head_and_clones(m->get_hobj())) {
201+
DEBUGDPP("{}.{}: {} possibly missing head or clone object on replica,"
202+
" bouncing to primary",
203+
pg, *this, this_instance_id, m->get_hobj());
203204
pg.get_perf_logger().inc(l_osd_replica_read_redirect_missing);
204205
co_await reply_op_error(pgref, -EAGAIN);
205206
co_return;
206207
} else if (!pg.get_peering_state().can_serve_replica_read(m->get_hobj())) {
208+
// Note: can_serve_replica_read checks for writes on the head object
209+
// as writes can only occur to head.
207210
DEBUGDPP("{}.{}: unstable write on replica, bouncing to primary",
208211
pg, *this, this_instance_id);
209212
pg.get_perf_logger().inc(l_osd_replica_read_redirect_conflict);
@@ -353,7 +356,8 @@ ClientRequest::process_op(
353356
}
354357

355358
std::set<snapid_t> snaps = snaps_need_to_recover();
356-
if (!snaps.empty()) {
359+
if (!snaps.empty() &&
360+
pg->is_missing_head_and_clones(m->get_hobj().get_head())) {
357361
co_await recover_missing_snaps(pg, snaps);
358362
}
359363
}

src/crimson/osd/pg.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,10 @@ void PG::context_registry_on_change() {
15111511
}
15121512
}
15131513

1514+
bool PG::is_missing_head_and_clones(const hobject_t &hoid) {
1515+
return peering_state.is_missing_any_head_or_clone_of(hoid);
1516+
}
1517+
15141518
bool PG::can_discard_op(const MOSDOp& m) const {
15151519
if (m.get_map_epoch() <
15161520
peering_state.get_info().history.same_primary_since) {

src/crimson/osd/pg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,10 @@ class PG : public boost::intrusive_ref_counter<
952952
!peering_state.get_missing_loc().readable_with_acting(
953953
oid, get_actingset(), v);
954954
}
955+
956+
// check if any head or clone of this object is missing
957+
bool is_missing_head_and_clones(const hobject_t &hoid);
958+
955959
bool is_missing_on_peer(
956960
const pg_shard_t &peer,
957961
const hobject_t &soid) const {

src/osd/PeeringState.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,10 @@ class PeeringState : public MissingLoc::MappingInfo {
24412441
unsigned int get_num_missing() const {
24422442
return pg_log.get_missing().num_missing();
24432443
}
2444+
bool is_missing_any_head_or_clone_of(const hobject_t &hoid) {
2445+
const auto& missing = pg_log.get_missing();
2446+
return missing.is_missing_any_head_or_clone_of(hoid);
2447+
}
24442448

24452449
const MissingLoc &get_missing_loc() const {
24462450
return missing_loc;

src/osd/osd_types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4997,6 +4997,12 @@ class pg_missing_set : public pg_missing_const_i {
49974997
return false;
49984998
return true;
49994999
}
5000+
5001+
bool is_missing_any_head_or_clone_of(const hobject_t& oid) const {
5002+
return missing.lower_bound(oid.get_object_boundary()) !=
5003+
missing.lower_bound(oid.get_max_object_boundary());
5004+
}
5005+
50005006
eversion_t get_oldest_need() const {
50015007
if (missing.empty()) {
50025008
return eversion_t();

src/test/osd/types.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,35 @@ TEST(pg_missing_t, split_into)
14351435
EXPECT_TRUE(missing.is_missing(oid2));
14361436
}
14371437

1438+
TEST(pg_missing_t, is_missing_any_head_or_clone_of)
1439+
{
1440+
hobject_t head_oid(object_t("objname"), "key", 123, 456, 0, "");
1441+
auto clone_oid = head_oid;
1442+
clone_oid.snap = 1;
1443+
1444+
// empty missing
1445+
pg_missing_t missing;
1446+
EXPECT_FALSE(missing.is_missing(head_oid));
1447+
EXPECT_FALSE(missing.is_missing_any_head_or_clone_of(head_oid));
1448+
EXPECT_FALSE(missing.is_missing(clone_oid));
1449+
EXPECT_FALSE(missing.is_missing_any_head_or_clone_of(clone_oid));
1450+
1451+
// only head is missing
1452+
missing.add(head_oid, eversion_t(), eversion_t(), false);
1453+
EXPECT_TRUE(missing.is_missing(head_oid));
1454+
EXPECT_TRUE(missing.is_missing_any_head_or_clone_of(head_oid));
1455+
EXPECT_FALSE(missing.is_missing(clone_oid));
1456+
EXPECT_TRUE(missing.is_missing_any_head_or_clone_of(clone_oid));
1457+
1458+
// only clone is missing
1459+
pg_missing_t missing2;
1460+
missing2.add(clone_oid, eversion_t(), eversion_t(), false);
1461+
EXPECT_FALSE(missing2.is_missing(head_oid));
1462+
EXPECT_TRUE(missing2.is_missing_any_head_or_clone_of(head_oid));
1463+
EXPECT_TRUE(missing2.is_missing(clone_oid));
1464+
EXPECT_TRUE(missing2.is_missing_any_head_or_clone_of(clone_oid));
1465+
}
1466+
14381467
TEST(pg_pool_t_test, get_pg_num_divisor) {
14391468
pg_pool_t p;
14401469
p.set_pg_num(16);

0 commit comments

Comments
 (0)