In replicated read scenario we first check if is_unreadable_object
for the head object. If so, l_osd_replica_read_redirect_missing is
incremented.
Later on, we check if can_serve_replica_read, if we've seen any writes
on this object(head) l_osd_replica_read_redirect_conflict is incremented.
Lastly, the object context is needed to be obtained
(find_object_context), if the requested object is a clone object -
we will need to resolve it to the corresponding actual object from
the OSD prespective.
There could be cases where the clone object is actually missing and
we would have to drop the replicated read rather late in the flow -
only once find_object_context will fail to get the relevant obc.
Moreover, in this case l_osd_replica_read_redirect_missing is not
incremented while l_osd_replica_read_served was already incremented even
if it was dropped.
We could alternatively, update the perf counters in the correct manner
but it seem that it's safer to avoid this niche and error prone path
in the first place.
See (pg_missing_t, is_missing_any_head_or_clone_of) tests for example on
the new check added.
Signed-off-by: Matan Breizman <mbreizma@redhat.com>
// missing object?
if (is_unreadable_object(head)) {
- if (!is_primary()) {
+ if (!is_primary() && is_missing_any_head_or_clone_of(head)) {
+ dout(10) << __func__ << "possibly missing clone object " << head
+ << " on this replica, bouncing to primary" << dendl;
osd->logger->inc(l_osd_replica_read_redirect_missing);
osd->reply_op_error(op, -EAGAIN);
return;
!recovery_state.get_missing_loc().readable_with_acting(
oid, get_actingset());
}
+ bool is_missing_any_head_or_clone_of(const hobject_t &hoid) {
+ return recovery_state.is_missing_any_head_or_clone_of(hoid);
+ }
void maybe_kick_recovery(const hobject_t &soid);
void wait_for_unreadable_object(const hobject_t& oid, OpRequestRef op);
void finish_unreadable_object(const hobject_t oid);