diff --git a/blockstore.cpp b/blockstore.cpp index adfe82f1..b2bafdea 100644 --- a/blockstore.cpp +++ b/blockstore.cpp @@ -176,9 +176,32 @@ void blockstore::loop() } } -bool blockstore::stop() +bool blockstore::is_safe_to_stop() { - return false; + // It's safe to stop blockstore when there are no in-flight operations, + // no in-progress syncs and flusher isn't doing anything + if (submit_queue.size() > 0 || in_progress_syncs.size() > 0 || flusher->is_active()) + { + return false; + } + if (unsynced_big_writes.size() > 0 || unsynced_small_writes.size() > 0) + { + if (!stop_sync_submitted) + { + // We should sync the blockstore before unmounting + blockstore_operation *op = new blockstore_operation; + op->flags = OP_SYNC; + op->buf = NULL; + op->callback = [&](blockstore_operation *op) + { + delete op; + }; + enqueue_op(op); + stop_sync_submitted = true; + } + return false; + } + return true; } void blockstore::check_wait(blockstore_operation *op) diff --git a/blockstore.h b/blockstore.h index 60a1792c..9b07f9d7 100644 --- a/blockstore.h +++ b/blockstore.h @@ -271,6 +271,8 @@ class blockstore ring_loop_t *ringloop; + bool stop_sync_submitted; + inline struct io_uring_sqe* get_sqe() { return ringloop->get_sqe(); @@ -327,12 +329,14 @@ public: // Event loop void loop(); + // Returns true when blockstore is ready to process operations + // (Although you're free to enqueue them before that) bool is_started(); // Returns true when it's safe to destroy the instance. If destroying the instance // requires to purge some queues, starts that process. Should be called in the event // loop until it returns true. - bool stop(); + bool is_safe_to_stop(); // Submission void enqueue_op(blockstore_operation *op); diff --git a/blockstore_flush.cpp b/blockstore_flush.cpp index c0420f6b..e02d21f5 100644 --- a/blockstore_flush.cpp +++ b/blockstore_flush.cpp @@ -41,6 +41,11 @@ journal_flusher_t::~journal_flusher_t() delete[] co; } +bool journal_flusher_t::is_active() +{ + return active_flushers > 0 || flush_queue.size() > 0; +} + void journal_flusher_t::loop() { for (int i = 0; i < flusher_count; i++) diff --git a/blockstore_flush.h b/blockstore_flush.h index bde09ee6..0656f06c 100644 --- a/blockstore_flush.h +++ b/blockstore_flush.h @@ -70,6 +70,7 @@ public: journal_flusher_t(int flusher_count, blockstore *bs); ~journal_flusher_t(); void loop(); + bool is_active(); void queue_flush(obj_ver_id oid); void unshift_flush(obj_ver_id oid); }; diff --git a/blockstore_sync.cpp b/blockstore_sync.cpp index 25093243..f7eb0874 100644 --- a/blockstore_sync.cpp +++ b/blockstore_sync.cpp @@ -11,6 +11,7 @@ int blockstore::dequeue_sync(blockstore_operation *op) { if (op->sync_state == 0) { + stop_sync_submitted = false; op->sync_big_writes.swap(unsynced_big_writes); op->sync_small_writes.swap(unsynced_small_writes); if (op->sync_big_writes.size() > 0)