diff mbox series

[1/3] blockdev: abort transactions in reverse order

Message ID 20181206192544.3987-2-jsnow@redhat.com (mailing list archive)
State New, archived
Headers show
Series bitmaps: remove x- prefix from QMP api | expand

Commit Message

John Snow Dec. 6, 2018, 7:25 p.m. UTC
Presently, we abort transactions in the same order they were processed in.
Bitmap commands, though, attempt to restore backup data structures on abort.
To that end, though, they need to be aborted in reverse chronological order.

Replace the QSIMPLEQ data structure with a QTAILQ one, so we can iterate
in reverse for the abort phase of the transaction.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 blockdev.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Comments

Eric Blake Dec. 6, 2018, 8:37 p.m. UTC | #1
On 12/6/18 1:25 PM, John Snow wrote:
> Presently, we abort transactions in the same order they were processed in.
> Bitmap commands, though, attempt to restore backup data structures on abort.
> To that end, though, they need to be aborted in reverse chronological order.
> 
> Replace the QSIMPLEQ data structure with a QTAILQ one, so we can iterate
> in reverse for the abort phase of the transaction.
> 
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>   blockdev.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)

Does this need to cc qemu-stable? I'm trying to figure out if it affects 
any of the transactions issued by my libvirt code demo'd at KVM Forum.

Reviewed-by: Eric Blake <eblake@redhat.com>
John Snow Dec. 6, 2018, 8:43 p.m. UTC | #2
On 12/6/18 3:37 PM, Eric Blake wrote:
> On 12/6/18 1:25 PM, John Snow wrote:
>> Presently, we abort transactions in the same order they were processed
>> in.
>> Bitmap commands, though, attempt to restore backup data structures on
>> abort.
>> To that end, though, they need to be aborted in reverse chronological
>> order.
>>
>> Replace the QSIMPLEQ data structure with a QTAILQ one, so we can iterate
>> in reverse for the abort phase of the transaction.
>>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>   blockdev.c | 14 +++++++-------
>>   1 file changed, 7 insertions(+), 7 deletions(-)
> 
> Does this need to cc qemu-stable? I'm trying to figure out if it affects
> any of the transactions issued by my libvirt code demo'd at KVM Forum.
> 
> Reviewed-by: Eric Blake <eblake@redhat.com>
> 

Hmm, possibly. merge is of course an x-prefix, but "clear" uses the same
restoration technique. I suppose if you cleared the same bitmap multiple
times and tried to roll it back you could see trouble where we restore
an already cleared bitmap.

I'll say that patch 01/03 here should be considered a bugfix, yes, but I
wanted to see if anyone thought this had consequences I hadn't
considered yet.

--js
Vladimir Sementsov-Ogievskiy Dec. 7, 2018, 8:38 a.m. UTC | #3
06.12.2018 22:25, John Snow wrote:
> Presently, we abort transactions in the same order they were processed in.
> Bitmap commands, though, attempt to restore backup data structures on abort.
> To that end, though, they need to be aborted in reverse chronological order.
> 
> Replace the QSIMPLEQ data structure with a QTAILQ one, so we can iterate
> in reverse for the abort phase of the transaction.

aha, so, abort for
   add
   disable
should be
   enable
   del
and not visa-versa

Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

> 
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>   blockdev.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/blockdev.c b/blockdev.c
> index 81f95d920b..1ba706df8b 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1341,7 +1341,7 @@ struct BlkActionState {
>       const BlkActionOps *ops;
>       JobTxn *block_job_txn;
>       TransactionProperties *txn_props;
> -    QSIMPLEQ_ENTRY(BlkActionState) entry;
> +    QTAILQ_ENTRY(BlkActionState) entry;
>   };
>   
>   /* internal snapshot private data */
> @@ -2269,8 +2269,8 @@ void qmp_transaction(TransactionActionList *dev_list,
>       BlkActionState *state, *next;
>       Error *local_err = NULL;
>   
> -    QSIMPLEQ_HEAD(snap_bdrv_states, BlkActionState) snap_bdrv_states;
> -    QSIMPLEQ_INIT(&snap_bdrv_states);
> +    QTAILQ_HEAD(snap_bdrv_states, BlkActionState) snap_bdrv_states;
> +    QTAILQ_INIT(&snap_bdrv_states);
>   
>       /* Does this transaction get canceled as a group on failure?
>        * If not, we don't really need to make a JobTxn.
> @@ -2301,7 +2301,7 @@ void qmp_transaction(TransactionActionList *dev_list,
>           state->action = dev_info;
>           state->block_job_txn = block_job_txn;
>           state->txn_props = props;
> -        QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
> +        QTAILQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
>   
>           state->ops->prepare(state, &local_err);
>           if (local_err) {
> @@ -2310,7 +2310,7 @@ void qmp_transaction(TransactionActionList *dev_list,
>           }
>       }
>   
> -    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
> +    QTAILQ_FOREACH(state, &snap_bdrv_states, entry) {
>           if (state->ops->commit) {
>               state->ops->commit(state);
>           }
> @@ -2321,13 +2321,13 @@ void qmp_transaction(TransactionActionList *dev_list,
>   
>   delete_and_fail:
>       /* failure, and it is all-or-none; roll back all operations */
> -    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
> +    QTAILQ_FOREACH_REVERSE(state, &snap_bdrv_states, snap_bdrv_states, entry) {
>           if (state->ops->abort) {
>               state->ops->abort(state);
>           }
>       }
>   exit:
> -    QSIMPLEQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
> +    QTAILQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
>           if (state->ops->clean) {
>               state->ops->clean(state);
>           }
>
diff mbox series

Patch

diff --git a/blockdev.c b/blockdev.c
index 81f95d920b..1ba706df8b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1341,7 +1341,7 @@  struct BlkActionState {
     const BlkActionOps *ops;
     JobTxn *block_job_txn;
     TransactionProperties *txn_props;
-    QSIMPLEQ_ENTRY(BlkActionState) entry;
+    QTAILQ_ENTRY(BlkActionState) entry;
 };
 
 /* internal snapshot private data */
@@ -2269,8 +2269,8 @@  void qmp_transaction(TransactionActionList *dev_list,
     BlkActionState *state, *next;
     Error *local_err = NULL;
 
-    QSIMPLEQ_HEAD(snap_bdrv_states, BlkActionState) snap_bdrv_states;
-    QSIMPLEQ_INIT(&snap_bdrv_states);
+    QTAILQ_HEAD(snap_bdrv_states, BlkActionState) snap_bdrv_states;
+    QTAILQ_INIT(&snap_bdrv_states);
 
     /* Does this transaction get canceled as a group on failure?
      * If not, we don't really need to make a JobTxn.
@@ -2301,7 +2301,7 @@  void qmp_transaction(TransactionActionList *dev_list,
         state->action = dev_info;
         state->block_job_txn = block_job_txn;
         state->txn_props = props;
-        QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
+        QTAILQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
 
         state->ops->prepare(state, &local_err);
         if (local_err) {
@@ -2310,7 +2310,7 @@  void qmp_transaction(TransactionActionList *dev_list,
         }
     }
 
-    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
+    QTAILQ_FOREACH(state, &snap_bdrv_states, entry) {
         if (state->ops->commit) {
             state->ops->commit(state);
         }
@@ -2321,13 +2321,13 @@  void qmp_transaction(TransactionActionList *dev_list,
 
 delete_and_fail:
     /* failure, and it is all-or-none; roll back all operations */
-    QSIMPLEQ_FOREACH(state, &snap_bdrv_states, entry) {
+    QTAILQ_FOREACH_REVERSE(state, &snap_bdrv_states, snap_bdrv_states, entry) {
         if (state->ops->abort) {
             state->ops->abort(state);
         }
     }
 exit:
-    QSIMPLEQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
+    QTAILQ_FOREACH_SAFE(state, &snap_bdrv_states, entry, next) {
         if (state->ops->clean) {
             state->ops->clean(state);
         }