---
 monitor/hmp-cmds.c   | 45 +++++++++++++++++++++++++++++++++-----------
 pve-backup.c         | 26 +++++++++++++++++++++----
 qapi/block-core.json |  9 +++++++--
 3 files changed, 63 insertions(+), 17 deletions(-)

diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 7fd59b1c22..4f692c15a2 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -218,19 +218,42 @@ void hmp_info_backup(Monitor *mon, const QDict *qdict)
             monitor_printf(mon, "End time: %s", ctime(&info->end_time));
         }
 
-        int per = (info->has_total && info->total &&
-            info->has_transferred && info->transferred) ?
-            (info->transferred * 100)/info->total : 0;
-        int zero_per = (info->has_total && info->total &&
-                        info->has_zero_bytes && info->zero_bytes) ?
-            (info->zero_bytes * 100)/info->total : 0;
         monitor_printf(mon, "Backup file: %s\n", info->backup_file);
         monitor_printf(mon, "Backup uuid: %s\n", info->uuid);
-        monitor_printf(mon, "Total size: %zd\n", info->total);
-        monitor_printf(mon, "Transferred bytes: %zd (%d%%)\n",
-                       info->transferred, per);
-        monitor_printf(mon, "Zero bytes: %zd (%d%%)\n",
-                       info->zero_bytes, zero_per);
+
+        if (!(info->has_total && info->total))  {
+            // this should not happen normally
+            monitor_printf(mon, "Total size: %d\n", 0);
+        } else {
+            bool incremental = false;
+            size_t total_or_dirty = info->total;
+            if (info->has_transferred) {
+                if (info->has_dirty && info->dirty) {
+                     if (info->dirty < info->total) {
+                        total_or_dirty = info->dirty;
+                        incremental = true;
+                    }
+                }
+            }
+
+            int per = (info->transferred * 100)/total_or_dirty;
+
+            monitor_printf(mon, "Backup mode: %s\n", incremental ? 
"incremental" : "full");
+
+            int zero_per = (info->has_zero_bytes && info->zero_bytes) ?
+                (info->zero_bytes * 100)/info->total : 0;
+            monitor_printf(mon, "Total size: %zd\n", info->total);
+            monitor_printf(mon, "Transferred bytes: %zd (%d%%)\n",
+                           info->transferred, per);
+            monitor_printf(mon, "Zero bytes: %zd (%d%%)\n",
+                           info->zero_bytes, zero_per);
+
+            if (info->has_reused) {
+                int reused_per = (info->reused * 100)/total_or_dirty;
+                monitor_printf(mon, "Reused bytes: %zd (%d%%)\n",
+                               info->reused, reused_per);
+            }
+        }
     }
 
     qapi_free_BackupStatus(info);
diff --git a/pve-backup.c b/pve-backup.c
index 1c4f6cf9e0..3a71270213 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -41,7 +41,9 @@ static struct PVEBackupState {
         uuid_t uuid;
         char uuid_str[37];
         size_t total;
+        size_t dirty;
         size_t transferred;
+        size_t reused;
         size_t zero_bytes;
     } stat;
     int64_t speed;
@@ -108,11 +110,12 @@ static bool pvebackup_error_or_canceled(void)
     return error_or_canceled;
 }
 
-static void pvebackup_add_transfered_bytes(size_t transferred, size_t 
zero_bytes)
+static void pvebackup_add_transfered_bytes(size_t transferred, size_t 
zero_bytes, size_t reused)
 {
     qemu_mutex_lock(&backup_state.stat.lock);
     backup_state.stat.zero_bytes += zero_bytes;
     backup_state.stat.transferred += transferred;
+    backup_state.stat.reused += reused;
     qemu_mutex_unlock(&backup_state.stat.lock);
 }
 
@@ -151,7 +154,8 @@ pvebackup_co_dump_pbs_cb(
         pvebackup_propagate_error(local_err);
         return pbs_res;
     } else {
-        pvebackup_add_transfered_bytes(size, !buf ? size : 0);
+        size_t reused = (pbs_res == 0) ? size : 0;
+        pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
     }
 
     return size;
@@ -211,11 +215,11 @@ pvebackup_co_dump_vma_cb(
         } else {
             if (remaining >= VMA_CLUSTER_SIZE) {
                 assert(ret == VMA_CLUSTER_SIZE);
-                pvebackup_add_transfered_bytes(VMA_CLUSTER_SIZE, zero_bytes);
+                pvebackup_add_transfered_bytes(VMA_CLUSTER_SIZE, zero_bytes, 
0);
                 remaining -= VMA_CLUSTER_SIZE;
             } else {
                 assert(ret == remaining);
-                pvebackup_add_transfered_bytes(remaining, zero_bytes);
+                pvebackup_add_transfered_bytes(remaining, zero_bytes, 0);
                 remaining = 0;
             }
         }
@@ -650,6 +654,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
     }
 
     size_t total = 0;
+    size_t dirty = 0;
 
     l = di_list;
     while (l) {
@@ -731,11 +736,14 @@ static void coroutine_fn pvebackup_co_prepare(void 
*opaque)
                     }
                     /* mark entire bitmap as dirty to make full backup first */
                     bdrv_set_dirty_bitmap(bitmap, 0, di->size);
+                    dirty += di->size;
                 } else {
                     use_incremental = true;
+                    dirty += bdrv_get_dirty_count(bitmap);
                 }
                 di->bitmap = bitmap;
             } else if (bitmap != NULL) {
+                dirty += di->size;
                 bdrv_release_dirty_bitmap(bitmap);
             }
 
@@ -751,6 +759,8 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
             di->dev_id = dev_id;
         }
     } else if (format == BACKUP_FORMAT_VMA) {
+        dirty = total;
+
         vmaw = vma_writer_create(task->backup_file, uuid, &local_err);
         if (!vmaw) {
             if (local_err) {
@@ -778,6 +788,8 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
             }
         }
     } else if (format == BACKUP_FORMAT_DIR) {
+        dirty = total;
+
         if (mkdir(task->backup_file, 0640) != 0) {
             error_setg_errno(task->errp, errno, "can't create directory 
'%s'\n",
                              task->backup_file);
@@ -850,8 +862,10 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
     char *uuid_str = g_strdup(backup_state.stat.uuid_str);
 
     backup_state.stat.total = total;
+    backup_state.stat.dirty = dirty;
     backup_state.stat.transferred = 0;
     backup_state.stat.zero_bytes = 0;
+    backup_state.stat.reused = 0;
 
     qemu_mutex_unlock(&backup_state.stat.lock);
 
@@ -1009,10 +1023,14 @@ BackupStatus *qmp_query_backup(Error **errp)
 
     info->has_total = true;
     info->total = backup_state.stat.total;
+    info->has_dirty = true;
+    info->dirty = backup_state.stat.dirty;
     info->has_zero_bytes = true;
     info->zero_bytes = backup_state.stat.zero_bytes;
     info->has_transferred = true;
     info->transferred = backup_state.stat.transferred;
+    info->has_reused = true;
+    info->reused = backup_state.stat.reused;
 
     qemu_mutex_unlock(&backup_state.stat.lock);
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index f693bebdb4..8ffff7aaab 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -757,8 +757,13 @@
 #
 # @total: total amount of bytes involved in the backup process
 #
+# @dirty: with incremental mode, this is the amount of bytes involved
+#         in the backup process which are marked dirty.
+#
 # @transferred: amount of bytes already backed up.
 #
+# @reused: amount of bytes reused due to deduplication.
+#
 # @zero-bytes: amount of 'zero' bytes detected.
 #
 # @start-time: time (epoch) when backup job started.
@@ -771,8 +776,8 @@
 #
 ##
 { 'struct': 'BackupStatus',
-  'data': {'*status': 'str', '*errmsg': 'str', '*total': 'int',
-           '*transferred': 'int', '*zero-bytes': 'int',
+  'data': {'*status': 'str', '*errmsg': 'str', '*total': 'int', '*dirty': 
'int',
+           '*transferred': 'int', '*zero-bytes': 'int', '*reused': 'int',
            '*start-time': 'int', '*end-time': 'int',
            '*backup-file': 'str', '*uuid': 'str' } }
 
-- 
2.20.1

_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to