瀏覽代碼

transactions: Invoke clean() after everything else

Invoke the transaction drivers' .clean() methods only after all
.commit() or .abort() handlers are done.

This makes it easier to have nested transactions where the top-level
transactions pass objects to lower transactions that the latter can
still use throughout their commit/abort phases, while the top-level
transaction keeps a reference that is released in its .clean() method.

(Before this commit, that is also possible, but the top-level
transaction would need to take care to invoke tran_add() before the
lower-level transaction does.  This commit makes the ordering
irrelevant, which is just a bit nicer.)

Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20211111120829.81329-8-hreitz@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20211115145409.176785-8-kwolf@redhat.com>
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Hanna Reitz 3 年之前
父節點
當前提交
079bff693b
共有 2 個文件被更改,包括 9 次插入2 次删除
  1. 3 0
      include/qemu/transactions.h
  2. 6 2
      util/transactions.c

+ 3 - 0
include/qemu/transactions.h

@@ -31,6 +31,9 @@
  * tran_create(), call your "prepare" functions on it, and finally call
  * tran_create(), call your "prepare" functions on it, and finally call
  * tran_abort() or tran_commit() to finalize the transaction by corresponding
  * tran_abort() or tran_commit() to finalize the transaction by corresponding
  * finalization actions in reverse order.
  * finalization actions in reverse order.
+ *
+ * The clean() functions registered by the drivers in a transaction are called
+ * last, after all abort() or commit() functions have been called.
  */
  */
 
 
 #ifndef QEMU_TRANSACTIONS_H
 #ifndef QEMU_TRANSACTIONS_H

+ 6 - 2
util/transactions.c

@@ -61,11 +61,13 @@ void tran_abort(Transaction *tran)
 {
 {
     TransactionAction *act, *next;
     TransactionAction *act, *next;
 
 
-    QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
+    QSLIST_FOREACH(act, &tran->actions, entry) {
         if (act->drv->abort) {
         if (act->drv->abort) {
             act->drv->abort(act->opaque);
             act->drv->abort(act->opaque);
         }
         }
+    }
 
 
+    QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
         if (act->drv->clean) {
         if (act->drv->clean) {
             act->drv->clean(act->opaque);
             act->drv->clean(act->opaque);
         }
         }
@@ -80,11 +82,13 @@ void tran_commit(Transaction *tran)
 {
 {
     TransactionAction *act, *next;
     TransactionAction *act, *next;
 
 
-    QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
+    QSLIST_FOREACH(act, &tran->actions, entry) {
         if (act->drv->commit) {
         if (act->drv->commit) {
             act->drv->commit(act->opaque);
             act->drv->commit(act->opaque);
         }
         }
+    }
 
 
+    QSLIST_FOREACH_SAFE(act, &tran->actions, entry, next) {
         if (act->drv->clean) {
         if (act->drv->clean) {
             act->drv->clean(act->opaque);
             act->drv->clean(act->opaque);
         }
         }