return false;
}
+ bool has_write_since(const hobject_t &oid, const eversion_t &bound) const {
+ for (auto i = log.rbegin(); i != log.rend(); ++i) {
+ if (i->version <= bound)
+ return false;
+ if (i->soid.get_head() == oid.get_head())
+ return true;
+ }
+ return false;
+ }
+
/// get a (bounded) list of recent reqids for the given object
void get_object_reqids(const hobject_t& oid, unsigned max,
mempool::osd_pglog::vector<pair<osd_reqid_t, version_t> > *pls,
bool needs_recovery() const;
bool needs_backfill() const;
+ /**
+ * Returns whether a particular object can be safely read on this replica
+ */
+ bool can_serve_replica_read(const hobject_t &hoid) {
+ ceph_assert(!is_primary());
+ return !pg_log.get_log().has_write_since(
+ hoid, get_min_last_complete_ondisk());
+ }
+
/**
* Returns whether all peers which might have unfound objects have been
* queried or marked lost.
return;
}
+ if (!is_primary()) {
+ if (!recovery_state.can_serve_replica_read(oid)) {
+ dout(20) << __func__ << ": oid " << oid
+ << " unstable write on replica, bouncing to primary."
+ << *m << dendl;
+ osd->reply_op_error(op, -EAGAIN);
+ return;
+ } else {
+ dout(20) << __func__ << ": serving replica read on oid" << oid
+ << dendl;
+ }
+ }
+
int r = find_object_context(
oid, &obc, can_create,
m->has_flag(CEPH_OSD_FLAG_MAP_SNAP_CLONE),