ldout(cct, 20) << "pending=" << count << dendl;
ceph_assert(pending_count == 0);
- pending_count = count;
- lock.Unlock();
- // if no pending requests, completion will fire now
- unblock();
+ if (count > 0) {
+ pending_count = count;
+ lock.Unlock();
+ } else {
+ pending_count = 1;
+ lock.Unlock();
+
+ // ensure completion fires in clean lock context
+ ictx->op_work_queue->queue(new C_AioRequest(this), 0);
+ }
}
void AioCompletion::complete_request(ssize_t r)
ldout(cct, 20) << "cb=" << complete_cb << ", "
<< "pending=" << pending_count << dendl;
- if (!count && blockers == 0) {
+ if (!count) {
finalize(rval);
complete();
}
void *complete_arg;
rbd_completion_t rbd_comp;
uint32_t pending_count; ///< number of requests
- uint32_t blockers;
int ref;
bool released;
ImageCtx *ictx;
AioCompletion() : lock("AioCompletion::lock", true, false),
state(AIO_STATE_PENDING), rval(0), complete_cb(NULL),
complete_arg(NULL), rbd_comp(NULL),
- pending_count(0), blockers(1),
- ref(1), released(false), ictx(NULL),
+ pending_count(0), ref(1), released(false), ictx(NULL),
aio_type(AIO_TYPE_NONE), m_xlist_item(this),
event_notify(false) {
}
}
}
- void block() {
- Mutex::Locker l(lock);
- ++blockers;
- }
- void unblock() {
- Mutex::Locker l(lock);
- ceph_assert(blockers > 0);
- --blockers;
- if (pending_count == 0 && blockers == 0) {
- finalize(rval);
- complete();
- }
- }
-
void set_event_notify(bool s) {
Mutex::Locker l(lock);
event_notify = s;
send_object_requests(object_extents, snapc, journal_tid);
} else {
// no IO to perform -- fire completion
- aio_comp->unblock();
+ aio_comp->set_request_count(0);
}
update_stats(clip_len);
// it wouldn't have been recorded in the journal
ldout(cct, 5) << ": no-op IO event beyond image size" << dendl;
aio_comp->get();
- aio_comp->unblock();
+ aio_comp->set_request_count(0);
aio_comp->put();
return true;
}