namespace {
template <typename ImageCtxT = ImageCtx>
-struct C_DiscardJournalCommit : public Context {
+struct C_DiscardRequest {
typedef std::vector<ObjectExtent> ObjectExtents;
ImageCtxT &image_ctx;
- AioCompletion *aio_comp;
+ AioCompletion *aio_completion;
ObjectExtents object_extents;
- C_DiscardJournalCommit(ImageCtxT &_image_ctx, AioCompletion *_aio_comp,
- const ObjectExtents &_object_extents, uint64_t tid)
- : image_ctx(_image_ctx), aio_comp(_aio_comp),
- object_extents(_object_extents) {
+ C_DiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_completion,
+ const ObjectExtents &object_extents)
+ : image_ctx(image_ctx), aio_completion(aio_completion),
+ object_extents(object_extents) {
+ aio_completion->add_request();
+ }
+
+ void send() {
+ discard_writeback();
+ }
+
+ void discard_writeback() {
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << "C_DiscardRequest: delaying cache discard until "
+ << "writeback flushed" << dendl;
+
+ // ensure we aren't holding the cache lock post-write
+ auto ctx = util::create_async_context_callback(
+ image_ctx, util::create_context_callback<
+ C_DiscardRequest<ImageCtxT>,
+ &C_DiscardRequest<ImageCtxT>::handle_discard_writeback>(this));
+
+ // ensure any in-flight writeback is complete before advancing
+ // the discard request
+ Mutex::Locker cache_locker(image_ctx.cache_lock);
+ image_ctx.object_cacher->discard_writeback(image_ctx.object_set,
+ object_extents, ctx);
+ }
+
+ void handle_discard_writeback(int r) {
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << "C_DiscardRequest: writeback flushed: " << r << dendl;
+
+ {
+ Mutex::Locker cache_locker(image_ctx.cache_lock);
+ image_ctx.object_cacher->discard_set(image_ctx.object_set,
+ object_extents);
+ }
+ aio_completion->complete_request(r);
+ delete this;
+ }
+};
+
+template <typename ImageCtxT = ImageCtx>
+struct C_DiscardJournalCommit : public Context {
+ ImageCtxT &image_ctx;
+ C_DiscardRequest<ImageCtxT> *discard_request;
+
+ C_DiscardJournalCommit(ImageCtxT &_image_ctx,
+ C_DiscardRequest<ImageCtxT> *discard_request,
+ uint64_t tid)
+ : image_ctx(_image_ctx), discard_request(discard_request) {
CephContext *cct = image_ctx.cct;
ldout(cct, 20) << "delaying cache discard until journal tid " << tid << " "
<< "safe" << dendl;
-
- aio_comp->add_request();
}
void finish(int r) override {
CephContext *cct = image_ctx.cct;
ldout(cct, 20) << "C_DiscardJournalCommit: "
<< "journal committed: discarding from cache" << dendl;
-
- Mutex::Locker cache_locker(image_ctx.cache_lock);
- image_ctx.object_cacher->discard_set(image_ctx.object_set, object_extents);
- aio_comp->complete_request(r);
+ discard_request->send();
}
};
if (!object_extents.empty()) {
uint64_t journal_tid = 0;
aio_comp->set_request_count(
- object_extents.size() + get_object_cache_request_count(journaling));
+ object_extents.size() + get_object_cache_request_count());
ObjectRequests requests;
send_object_requests(object_extents, snapc,
}
template <typename I>
-uint32_t ImageDiscardRequest<I>::get_object_cache_request_count(bool journaling) const {
- // extra completion request is required for tracking journal commit
+uint32_t ImageDiscardRequest<I>::get_object_cache_request_count() const {
+ // extra completion request is required for tracking discard
I &image_ctx = this->m_image_ctx;
- return (image_ctx.object_cacher != nullptr && journaling ? 1 : 0);
+ return (image_ctx.object_cacher != nullptr ? 1 : 0);
}
template <typename I>
void ImageDiscardRequest<I>::send_object_cache_requests(
const ObjectExtents &object_extents, uint64_t journal_tid) {
I &image_ctx = this->m_image_ctx;
+ auto aio_comp = this->m_aio_comp;
+ auto req = new C_DiscardRequest<I>(image_ctx, aio_comp, object_extents);
if (journal_tid == 0) {
- Mutex::Locker cache_locker(image_ctx.cache_lock);
- image_ctx.object_cacher->discard_set(image_ctx.object_set,
- object_extents);
+ req->send();
} else {
// cannot discard from cache until journal has committed
assert(image_ctx.journal != NULL);
- AioCompletion *aio_comp = this->m_aio_comp;
image_ctx.journal->wait_event(
- journal_tid, new C_DiscardJournalCommit<I>(image_ctx, aio_comp,
- object_extents, journal_tid));
+ journal_tid, new C_DiscardJournalCommit<I>(image_ctx, req, journal_tid));
}
}
return tid;
}
+template <typename I>
+uint32_t ImageCompareAndWriteRequest<I>::get_object_cache_request_count() const {
+ // extra completion request is required for tracking discard
+ I &image_ctx = this->m_image_ctx;
+ return (image_ctx.object_cacher != nullptr ? 1 : 0);
+}
+
template <typename I>
void ImageCompareAndWriteRequest<I>::send_object_cache_requests(
const ObjectExtents &object_extents, uint64_t journal_tid) {
I &image_ctx = this->m_image_ctx;
if (image_ctx.object_cacher != NULL) {
- Mutex::Locker cache_locker(image_ctx.cache_lock);
- image_ctx.object_cacher->discard_set(image_ctx.object_set,
- object_extents);
+ auto aio_comp = this->m_aio_comp;
+ auto req = new C_DiscardRequest<I>(image_ctx, aio_comp, object_extents);
+ req->send();
}
}