From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Fabian Ebner <f.ebner@proxmox.com>
Date: Wed, 25 May 2022 13:59:37 +0200
Subject: [PATCH] PVE-Backup: create jobs: correctly cancel in error scenario

The first call to job_cancel_sync() will cancel and free all jobs in
the transaction, so ensure that it's called only once and get rid of
the job_unref() that would operate on freed memory.

It's also necessary to NULL backup_state.pbs in the error scenario,
because a subsequent backup_cancel QMP call (as happens in PVE when
the backup QMP command fails) would try to call proxmox_backup_abort()
and run into a segfault.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
[FE: adapt for new job lock mechanism replacing AioContext locks]
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
 pve-backup.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/pve-backup.c b/pve-backup.c
index 262e7d3894..fde3554133 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -503,6 +503,11 @@ static void create_backup_jobs_bh(void *opaque) {
     }
 
     if (*errp) {
+        /*
+         * It's enough to cancel one job in the transaction, the rest will
+         * follow automatically.
+         */
+        bool canceled = false;
         l = backup_state.di_list;
         while (l) {
             PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
@@ -513,11 +518,11 @@ static void create_backup_jobs_bh(void *opaque) {
                 di->target = NULL;
             }
 
-            if (di->job) {
+            if (!canceled && di->job) {
                 WITH_JOB_LOCK_GUARD() {
                     job_cancel_sync_locked(&di->job->job, true);
-                    job_unref_locked(&di->job->job);
                 }
+                canceled = true;
             }
         }
     }
@@ -943,6 +948,7 @@ err:
 
     if (pbs) {
         proxmox_backup_disconnect(pbs);
+        backup_state.pbs = NULL;
     }
 
     if (backup_dir) {
