CephContext *cct = m_image_ctx.cct;
typename Events::iterator it = m_events.find(tid);
- if (it == m_events.end() || it->second.safe) {
+ assert(it != m_events.end());
+
+ Event &event = it->second;
+ if (event.safe) {
// journal entry already safe
ldout(cct, 20) << "journal entry already safe" << dendl;
- m_image_ctx.op_work_queue->queue(on_safe, 0);
+ m_image_ctx.op_work_queue->queue(on_safe, event.ret_val);
return Future();
}
- Event &event = it->second;
event.on_safe_contexts.push_back(on_safe);
return event.future;
}
ldout(cct, 20) << this << " " << __func__ << ": tid=" << it->first << " "
<< "r=" << r << dendl;
- m_journaler->committed(it->second.future);
- if (it->second.safe) {
+ Event &event = it->second;
+ if (r < 0) {
+ // event recorded to journal but failed to update disk, we cannot
+ // commit this IO event. this event must be replayed.
+ assert(event.safe);
+ lderr(cct) << "failed to commit IO to disk, replay required: "
+ << cpp_strerror(r) << dendl;
+ }
+
+ event.committed_io = true;
+ if (event.safe) {
+ if (r >= 0) {
+ m_journaler->committed(event.future);
+ }
m_events.erase(it);
}
}
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << ", "
<< "tid=" << tid << dendl;
- // TODO: ensure this callback never sees a failure
AioCompletion *aio_comp;
AioObjectRequests aio_object_requests;
Contexts on_safe_contexts;
aio_object_requests.swap(event.aio_object_requests);
on_safe_contexts.swap(event.on_safe_contexts);
- if (event.pending_extents.empty()) {
+ if (r < 0 || event.committed_io) {
+ // failed journal write so IO won't be sent -- or IO extent was
+ // overwritten by future IO operations so this was a no-op IO event
+ event.ret_val = r;
+ m_journaler->committed(event.future);
+ }
+
+ if (event.committed_io) {
m_events.erase(it);
} else {
event.safe = true;
struct Event {
Future future;
- AioCompletion *aio_comp;
+ AioCompletion *aio_comp = nullptr;
AioObjectRequests aio_object_requests;
Contexts on_safe_contexts;
ExtentInterval pending_extents;
- bool safe;
- int ret_val;
+ bool committed_io = false;
+ bool safe = false;
+ int ret_val = 0;
- Event() : aio_comp(NULL) {
+ Event() {
}
Event(const Future &_future, AioCompletion *_aio_comp,
const AioObjectRequests &_requests, uint64_t offset, size_t length)
- : future(_future), aio_comp(_aio_comp), aio_object_requests(_requests),
- safe(false), ret_val(0) {
+ : future(_future), aio_comp(_aio_comp), aio_object_requests(_requests) {
if (length > 0) {
pending_extents.insert(offset, length);
}