There still can be pending prezero requests after Journal::flush()
return. We should wait until all prezero requests are done, then
destroy the on-stack journaler.
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Fixes: http://tracker.ceph.com/issues/20549
(cherry picked from commit
9299a1ceb607199d2ea09662ee1ef280a7b9f920)
if (waiting_for_zero_pos > flush_pos) {
_do_flush(waiting_for_zero_pos - flush_pos);
}
+
+ if (prezero_pos == prezeroing_pos &&
+ !waitfor_prezero.empty()) {
+ list<Context*> ls;
+ ls.swap(waitfor_prezero);
+ finish_contexts(cct, ls, 0);
+ }
} else {
pending_zero.insert(start, len);
}
<< dendl;
}
+void Journaler::wait_for_prezero(Context *onfinish)
+{
+ assert(onfinish);
+ lock_guard l(lock);
+
+ if (prezero_pos == prezeroing_pos) {
+ finisher->queue(onfinish, 0);
+ return;
+ }
+ waitfor_prezero.push_back(wrap_finisher(onfinish));
+}
/***************** READING *******************/
uint64_t waiting_for_zero_pos;
interval_set<uint64_t> pending_zero; // non-contig bits we've zeroed
+ list<Context*> waitfor_prezero;
+
std::map<uint64_t, uint64_t> pending_safe; // flush_pos -> safe_pos
// when safe through given offset
std::map<uint64_t, std::list<Context*> > waitfor_safe;
void flush(Context *onsafe = 0);
void wait_for_readable(Context *onfinish);
bool have_waiter() const;
+ void wait_for_prezero(Context *onfinish);
// Synchronous setters
// ===================
bufferlist bl;
le->encode_with_header(bl, CEPH_FEATURES_SUPPORTED_DEFAULT);
-
+
cout << "writing EResetJournal entry" << std::endl;
- C_SaferCond cond;
journaler->append_entry(bl);
- journaler->flush(&cond);
- return cond.wait();
+ int ret;
+ {
+ C_SaferCond cond;
+ journaler->flush(&cond);
+ ret = cond.wait();
+ if (ret < 0)
+ return ret;
+ }
+ {
+ // wait until all journal prezero ops are done
+ C_SaferCond cond;
+ journaler->wait_for_prezero(&cond);
+ cond.wait();
+ }
+
+ return ret;
}