Since any thread can be the one that hits t_update == 0 (even if it
wasn't the one calling diskfs_journal_set_sync), and that thread can even be a
thread that cannot be made to wait for IO (the Pager since that would lead to
deadlocks), we have to change how this works and align better with the
guideline given in libdiskfs/diskfs.h about it.

The sync is now merely a signaling mechanism between the lower level function
and the top level caller so that top level might decide to invoke commit and
wait if it so chooses.

Under certain condition we still can commit on stop, but in an async
manner without blocking the calling thread.
---
 ext2fs/journal.c   | 26 ++++----------------------
 libdiskfs/diskfs.h |  5 +++--
 2 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/ext2fs/journal.c b/ext2fs/journal.c
index d4097da89..d58d7e914 100644
--- a/ext2fs/journal.c
+++ b/ext2fs/journal.c
@@ -2213,30 +2213,12 @@ static void
 diskfs_journal_stop_transaction_locked (journal_t *journal,
                                        diskfs_transaction_t *txn)
 {
-  uint32_t tid = txn->t_tid;
   journal_stop_transaction_locked (journal, txn);
 
-  /* Auto-commit? */
-  if (txn->t_updates == 0)
-    {
-      if (txn->sync_needed)
-       {
-         assert_backtrace (txn == journal->j_running_transaction
-                           || txn == journal->j_committing_transaction);
-         if (journal->j_running_transaction == txn)
-           {
-             error_t err =
-               journal_commit_running_transaction_locked (journal);
-             if (err)
-               JRNL_LOG_WARN ("Synchronous commit failed for TID %u: %s",
-                              tid, strerror (err));
-           }
-         else
-           journal_wait_on_tid_locked (journal, tid);
-       }
-      else if (txn->t_buffer_map.size >= journal->j_max_transaction_buffers)
-       pthread_cond_signal (&journal->j_flusher_wakeup);
-    }
+  /* Semi auto-commit? */
+  if (txn->t_updates == 0 && (txn->sync_needed ||
+      (txn->t_buffer_map.size >= journal->j_max_transaction_buffers)))
+    pthread_cond_signal (&journal->j_flusher_wakeup);
 }
 
 /* Ends the caller's participation in the given transaction TXN.
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index d8dac1293..b7f4f7896 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -547,8 +547,9 @@ diskfs_transaction_t *diskfs_journal_start_transaction 
(void);
    underlying journal to batch operations for performance.
 
    However, if any participant flagged the transaction for a synchronous commit
-   (e.g., via diskfs_journal_set_sync), the journal will automatically commit
-   and flush the transaction to disk once the final participant stops.
+   (e.g., via diskfs_journal_set_sync), or in other situations the journal
+   reserves the right to commit and flush the transaction to disk once the
+   conditions have been met.
 
    This function consumes TXN. The caller must not use TXN after this call. */
 void diskfs_journal_stop_transaction (diskfs_transaction_t *txn);
-- 
2.55.0


Reply via email to