break;
}
if (oi.is_dirty()) {
- result = start_flush(ctx, false);
+ result = start_flush(ctx, false, NULL);
} else {
result = 0;
}
result = 0;
break;
}
+ hobject_t missing;
if (oi.is_dirty()) {
- result = start_flush(ctx, true);
+ result = start_flush(ctx, true, &missing);
} else {
result = 0;
}
+ // Check special return value which has set missing_return
+ if (result == -ENOENT) {
+ dout(10) << __func__ << " CEPH_OSD_OP_CACHE_FLUSH got ENOENT" << dendl;
+ assert(!missing.is_min());
+ wait_for_unreadable_object(missing, ctx->op);
+ // Error code which is used elsewhere when wait_for_unreadable_object() is used
+ result = -EAGAIN;
+ }
}
break;
}
};
-int ReplicatedPG::start_flush(OpContext *ctx, bool blocking)
+int ReplicatedPG::start_flush(OpContext *ctx, bool blocking, hobject_t *pmissing)
{
const object_info_t& oi = ctx->obc->obs.oi;
const hobject_t& soid = oi.soid;
hobject_t next = soid;
next.snap = *p;
assert(next.snap < soid.snap);
+ if (pg_log.get_missing().is_missing(next)) {
+ dout(10) << __func__ << " missing clone is " << next << dendl;
+ if (pmissing)
+ *pmissing = next;
+ return -ENOENT;
+ }
ObjectContextRef older_obc = get_object_context(next, false);
if (older_obc) {
dout(20) << __func__ << " next oldest clone is " << older_obc->obs.oi
ctx->at_version = get_next_version();
ctx->on_finish = new C_AgentFlushStartStop(this, obc->obs.oi.soid);
- int result = start_flush(ctx, false);
+ int result = start_flush(ctx, false, NULL);
if (result != -EINPROGRESS) {
dout(10) << __func__ << " start_flush() failed " << obc->obs.oi
<< " with " << result << dendl;
// -- flush --
map<hobject_t, FlushOpRef> flush_ops;
- int start_flush(OpContext *ctx, bool blocking);
+ int start_flush(OpContext *ctx, bool blocking, hobject_t *pmissing);
void finish_flush(hobject_t oid, ceph_tid_t tid, int r);
int try_flush_mark_clean(FlushOpRef fop);
void cancel_flush(FlushOpRef fop, bool requeue);