mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
filestore: make OpSequencer::flush() work for writeahead journaling items
It was only waiting for items in the op_queue to complete. The goal is to wait for anything we've called queue_transactions(&osr,...) on. If we do writeahead journaling, though, there might be new ops that are still journaling but not yet submitted to the fs that are missed. This adds a journal queue to the OpSequencer, and uses it in the writeahead case only. Signed-off-by: Sage Weil <sage@newdream.net>
This commit is contained in:
parent
285f351b72
commit
3a235b0f21
@ -1230,7 +1230,7 @@ int FileStore::umount()
|
|||||||
|
|
||||||
/// -----------------------------
|
/// -----------------------------
|
||||||
|
|
||||||
void FileStore::queue_op(Sequencer *posr, uint64_t op_seq, list<Transaction*>& tls,
|
void FileStore::queue_op(OpSequencer *osr, uint64_t op_seq, list<Transaction*>& tls,
|
||||||
Context *onreadable, Context *onreadable_sync)
|
Context *onreadable, Context *onreadable_sync)
|
||||||
{
|
{
|
||||||
uint64_t bytes = 0, ops = 0;
|
uint64_t bytes = 0, ops = 0;
|
||||||
@ -1260,18 +1260,6 @@ void FileStore::queue_op(Sequencer *posr, uint64_t op_seq, list<Transaction*>& t
|
|||||||
|
|
||||||
op_tp.lock();
|
op_tp.lock();
|
||||||
|
|
||||||
OpSequencer *osr;
|
|
||||||
if (!posr)
|
|
||||||
posr = &default_osr;
|
|
||||||
if (posr->p) {
|
|
||||||
osr = (OpSequencer *)posr->p;
|
|
||||||
dout(10) << "queue_op existing osr " << osr << "/" << osr->parent << dendl; //<< " w/ q " << osr->q << dendl;
|
|
||||||
} else {
|
|
||||||
osr = new OpSequencer;
|
|
||||||
osr->parent = posr;
|
|
||||||
posr->p = osr;
|
|
||||||
dout(10) << "queue_op new osr " << osr << "/" << osr->parent << dendl;
|
|
||||||
}
|
|
||||||
osr->queue(o);
|
osr->queue(o);
|
||||||
|
|
||||||
op_queue_len++;
|
op_queue_len++;
|
||||||
@ -1361,13 +1349,13 @@ void FileStore::_finish_op(OpSequencer *osr)
|
|||||||
|
|
||||||
struct C_JournaledAhead : public Context {
|
struct C_JournaledAhead : public Context {
|
||||||
FileStore *fs;
|
FileStore *fs;
|
||||||
ObjectStore::Sequencer *osr;
|
FileStore::OpSequencer *osr;
|
||||||
uint64_t op;
|
uint64_t op;
|
||||||
list<ObjectStore::Transaction*> tls;
|
list<ObjectStore::Transaction*> tls;
|
||||||
Context *onreadable, *onreadable_sync;
|
Context *onreadable, *onreadable_sync;
|
||||||
Context *ondisk;
|
Context *ondisk;
|
||||||
|
|
||||||
C_JournaledAhead(FileStore *f, ObjectStore::Sequencer *os, uint64_t o, list<ObjectStore::Transaction*>& t,
|
C_JournaledAhead(FileStore *f, FileStore::OpSequencer *os, uint64_t o, list<ObjectStore::Transaction*>& t,
|
||||||
Context *onr, Context *ond, Context *onrsync) :
|
Context *onr, Context *ond, Context *onrsync) :
|
||||||
fs(f), osr(os), op(o), tls(t), onreadable(onr), onreadable_sync(onrsync), ondisk(ond) { }
|
fs(f), osr(os), op(o), tls(t), onreadable(onr), onreadable_sync(onrsync), ondisk(ond) { }
|
||||||
void finish(int r) {
|
void finish(int r) {
|
||||||
@ -1382,10 +1370,24 @@ int FileStore::queue_transaction(Sequencer *osr, Transaction *t)
|
|||||||
return queue_transactions(osr, tls, new C_DeleteTransaction(t));
|
return queue_transactions(osr, tls, new C_DeleteTransaction(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileStore::queue_transactions(Sequencer *osr, list<Transaction*> &tls,
|
int FileStore::queue_transactions(Sequencer *posr, list<Transaction*> &tls,
|
||||||
Context *onreadable, Context *ondisk,
|
Context *onreadable, Context *ondisk,
|
||||||
Context *onreadable_sync)
|
Context *onreadable_sync)
|
||||||
{
|
{
|
||||||
|
// set up the sequencer
|
||||||
|
OpSequencer *osr;
|
||||||
|
if (!posr)
|
||||||
|
posr = &default_osr;
|
||||||
|
if (posr->p) {
|
||||||
|
osr = (OpSequencer *)posr->p;
|
||||||
|
dout(10) << "queue_transactions existing osr " << osr << "/" << osr->parent << dendl; //<< " w/ q " << osr->q << dendl;
|
||||||
|
} else {
|
||||||
|
osr = new OpSequencer;
|
||||||
|
osr->parent = posr;
|
||||||
|
posr->p = osr;
|
||||||
|
dout(10) << "queue_transactions new osr " << osr << "/" << osr->parent << dendl;
|
||||||
|
}
|
||||||
|
|
||||||
if (journal && journal->is_writeable()) {
|
if (journal && journal->is_writeable()) {
|
||||||
if (g_conf.filestore_journal_parallel) {
|
if (g_conf.filestore_journal_parallel) {
|
||||||
|
|
||||||
@ -1414,6 +1416,7 @@ int FileStore::queue_transactions(Sequencer *osr, list<Transaction*> &tls,
|
|||||||
|
|
||||||
uint64_t op = op_submit_start();
|
uint64_t op = op_submit_start();
|
||||||
dout(10) << "queue_transactions (writeahead) " << op << " " << tls << dendl;
|
dout(10) << "queue_transactions (writeahead) " << op << " " << tls << dendl;
|
||||||
|
osr->queue_journal(op);
|
||||||
_op_journal_transactions(tls, op,
|
_op_journal_transactions(tls, op,
|
||||||
new C_JournaledAhead(this, osr, op, tls, onreadable, ondisk, onreadable_sync));
|
new C_JournaledAhead(this, osr, op, tls, onreadable, ondisk, onreadable_sync));
|
||||||
op_submit_finish(op);
|
op_submit_finish(op);
|
||||||
@ -1447,7 +1450,7 @@ int FileStore::queue_transactions(Sequencer *osr, list<Transaction*> &tls,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileStore::_journaled_ahead(Sequencer *osr, uint64_t op,
|
void FileStore::_journaled_ahead(OpSequencer *osr, uint64_t op,
|
||||||
list<Transaction*> &tls,
|
list<Transaction*> &tls,
|
||||||
Context *onreadable, Context *ondisk,
|
Context *onreadable, Context *ondisk,
|
||||||
Context *onreadable_sync)
|
Context *onreadable_sync)
|
||||||
@ -1456,6 +1459,8 @@ void FileStore::_journaled_ahead(Sequencer *osr, uint64_t op,
|
|||||||
|
|
||||||
op_queue_throttle();
|
op_queue_throttle();
|
||||||
|
|
||||||
|
osr->dequeue_journal();
|
||||||
|
|
||||||
// this should queue in order because the journal does it's completions in order.
|
// this should queue in order because the journal does it's completions in order.
|
||||||
journal_lock.Lock();
|
journal_lock.Lock();
|
||||||
queue_op(osr, op, tls, onreadable, onreadable_sync);
|
queue_op(osr, op, tls, onreadable, onreadable_sync);
|
||||||
|
@ -101,11 +101,21 @@ class FileStore : public JournalingObjectStore {
|
|||||||
class OpSequencer : public Sequencer_impl {
|
class OpSequencer : public Sequencer_impl {
|
||||||
Mutex qlock; // to protect q, for benefit of flush (peek/dequeue also protected by lock)
|
Mutex qlock; // to protect q, for benefit of flush (peek/dequeue also protected by lock)
|
||||||
list<Op*> q;
|
list<Op*> q;
|
||||||
|
list<uint64_t> jq;
|
||||||
Cond cond;
|
Cond cond;
|
||||||
public:
|
public:
|
||||||
Sequencer *parent;
|
Sequencer *parent;
|
||||||
Mutex apply_lock; // for apply mutual exclusion
|
Mutex apply_lock; // for apply mutual exclusion
|
||||||
|
|
||||||
|
void queue_journal(uint64_t s) {
|
||||||
|
Mutex::Locker l(qlock);
|
||||||
|
jq.push_back(s);
|
||||||
|
}
|
||||||
|
void dequeue_journal() {
|
||||||
|
Mutex::Locker l(qlock);
|
||||||
|
jq.pop_front();
|
||||||
|
cond.Signal();
|
||||||
|
}
|
||||||
void queue(Op *o) {
|
void queue(Op *o) {
|
||||||
Mutex::Locker l(qlock);
|
Mutex::Locker l(qlock);
|
||||||
q.push_back(o);
|
q.push_back(o);
|
||||||
@ -124,9 +134,18 @@ class FileStore : public JournalingObjectStore {
|
|||||||
}
|
}
|
||||||
void flush() {
|
void flush() {
|
||||||
Mutex::Locker l(qlock);
|
Mutex::Locker l(qlock);
|
||||||
if (!q.empty()) {
|
|
||||||
uint64_t seq = q.back()->op;
|
// get max for journal _or_ op queues
|
||||||
while (!q.empty() && q.front()->op <= seq)
|
uint64_t seq = 0;
|
||||||
|
if (!q.empty())
|
||||||
|
seq = q.back()->op;
|
||||||
|
if (!jq.empty() && jq.back() > seq)
|
||||||
|
seq = jq.back();
|
||||||
|
|
||||||
|
if (seq) {
|
||||||
|
// everything prior to our watermark to drain through either/both queues
|
||||||
|
while ((!q.empty() && q.front()->op <= seq) ||
|
||||||
|
(!jq.empty() && jq.front() <= seq))
|
||||||
cond.Wait(qlock);
|
cond.Wait(qlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,9 +199,9 @@ class FileStore : public JournalingObjectStore {
|
|||||||
|
|
||||||
void _do_op(OpSequencer *o);
|
void _do_op(OpSequencer *o);
|
||||||
void _finish_op(OpSequencer *o);
|
void _finish_op(OpSequencer *o);
|
||||||
void queue_op(Sequencer *osr, uint64_t op, list<Transaction*>& tls, Context *onreadable, Context *onreadable_sync);
|
void queue_op(OpSequencer *osr, uint64_t op, list<Transaction*>& tls, Context *onreadable, Context *onreadable_sync);
|
||||||
void op_queue_throttle();
|
void op_queue_throttle();
|
||||||
void _journaled_ahead(Sequencer *osr, uint64_t op, list<Transaction*> &tls,
|
void _journaled_ahead(OpSequencer *osr, uint64_t op, list<Transaction*> &tls,
|
||||||
Context *onreadable, Context *ondisk, Context *onreadable_sync);
|
Context *onreadable, Context *ondisk, Context *onreadable_sync);
|
||||||
friend class C_JournaledAhead;
|
friend class C_JournaledAhead;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user