From: Shannon Sterz <s.sterz@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH cluster 04/21] pmxcfs: add ability to query backup progress
Date: Fri, 28 Aug 2026 15:30:13 +0200 [thread overview]
Message-ID: <20260828133030.351140-5-s.sterz@proxmox.com> (raw)
In-Reply-To: <20260828133030.351140-1-s.sterz@proxmox.com>
cfs_live_backup_database() will now also return the progress of the
backup instead of just the filename.
Signed-off-by: Shannon Sterz <s.sterz@proxmox.com>
---
src/PVE/Cluster.pm | 43 +++++++++++++++++++++++++++++++++++-----
src/pmxcfs/cfs-ipc-ops.h | 2 ++
src/pmxcfs/database.c | 18 +++++++++++++++++
src/pmxcfs/memdb.c | 12 +++++++++++
src/pmxcfs/memdb.h | 28 ++++++++++++++++++++++++++
src/pmxcfs/server.c | 11 ++++++++++
src/pmxcfs/status.c | 7 +++++++
src/pmxcfs/status.h | 2 ++
8 files changed, 118 insertions(+), 5 deletions(-)
diff --git a/src/PVE/Cluster.pm b/src/PVE/Cluster.pm
index 31c06e8..b907f2e 100644
--- a/src/PVE/Cluster.pm
+++ b/src/PVE/Cluster.pm
@@ -243,8 +243,14 @@ my $ipcc_init_backup = sub {
my ($filename) = @_;
my $bindata = pack "Z*", $filename;
- PVE::IPCC::ipcc_send_rec(CFS_IPC_INIT_BACKUP, $bindata);
- warn $! if $! != 0;
+ my $result = &$ipcc_send_rec_json(CFS_IPC_INIT_BACKUP, $bindata);
+ die $! if $! != 0;
+
+ return $result;
+};
+
+my $ipcc_backup_progress = sub {
+ return &$ipcc_send_rec_json(CFS_IPC_BACKUP_PROGRESS);
};
my $ccache = {};
@@ -943,7 +949,11 @@ sub cfs_rename_db_unsafe {
Creates a new live backup of the database backing the cluster file system.
-Returns a file path to the created backup.
+Returns a hash with two members: C<file> is the filename of the new backups and
+C<progress> which is also a hash. C<progress> has three members: C<in-progress>,
+a boolean indicating whether the backup is finished or still on-going,
+C<remaining>, an integer showing the pages that are not yet backed up, and
+C<total> showing the total page count.
=cut
@@ -964,12 +974,35 @@ sub cfs_live_backup_database {
my $ctime = time();
my $backup_file = "config-backup-$ctime.db";
print "starting backup of current database to \"$dbbackupdir/$backup_file\"\n";
+ my $result = {};
- eval { &$ipcc_init_backup($backup_file); };
+ eval { $result = &$ipcc_init_backup($backup_file); };
+ die $@ if $@;
+ return {
+ 'file' => $backup_file,
+ 'progress' => $result,
+ };
+}
+
+=head3 cfs_live_backup_progress()
+
+Returns a hash that describes the current live backup status of the database
+backing the cluster file system.
+
+It contains three members: C<in-progress>, a boolean indicating whether the
+backup is finished or still on-going, C<remaining>, an integer showing the pages
+that are not yet backed up, and C<total> showing the total page count.
+
+=cut
+
+sub cfs_live_backup_progress {
+ my $result = {};
+
+ eval { $result = &$ipcc_backup_progress(); };
warn $@ if $@;
- return $backup_file;
+ return $result;
}
1;
diff --git a/src/pmxcfs/cfs-ipc-ops.h b/src/pmxcfs/cfs-ipc-ops.h
index 054ebb3..e8f7541 100644
--- a/src/pmxcfs/cfs-ipc-ops.h
+++ b/src/pmxcfs/cfs-ipc-ops.h
@@ -47,4 +47,6 @@
#define CFS_IPC_INIT_BACKUP 14
+#define CFS_IPC_BACKUP_PROGRESS 15
+
#endif
diff --git a/src/pmxcfs/database.c b/src/pmxcfs/database.c
index 07b3664..39bdf61 100644
--- a/src/pmxcfs/database.c
+++ b/src/pmxcfs/database.c
@@ -866,3 +866,21 @@ int bdb_handle_backup(db_backend_t *bdb) {
return to_return_code;
}
+
+memdb_backup_progress_t bdb_backup_progress(db_backend_t *bdb) {
+ memdb_backup_progress_t to_return = {
+ .in_progress = FALSE,
+ .remaining = 0,
+ .total = 0,
+ };
+
+ if (bdb == NULL || bdb->current_backup == NULL) {
+ return to_return;
+ }
+
+ to_return.in_progress = TRUE;
+ to_return.remaining = sqlite3_backup_remaining(bdb->current_backup);
+ to_return.total = sqlite3_backup_pagecount(bdb->current_backup);
+
+ return to_return;
+}
diff --git a/src/pmxcfs/memdb.c b/src/pmxcfs/memdb.c
index b7372f9..255c03f 100644
--- a/src/pmxcfs/memdb.c
+++ b/src/pmxcfs/memdb.c
@@ -1550,3 +1550,15 @@ int memdb_handle_backup(memdb_t *memdb) {
return to_return;
}
+
+memdb_backup_progress_t memdb_backup_progress(memdb_t *memdb) {
+ memdb_backup_progress_t to_return = {
+ .in_progress = FALSE,
+ .remaining = 0,
+ .total = 0,
+ };
+
+ g_return_val_if_fail(memdb != NULL, to_return);
+
+ return bdb_backup_progress(memdb->bdb);
+}
diff --git a/src/pmxcfs/memdb.h b/src/pmxcfs/memdb.h
index 2c27959..3943328 100644
--- a/src/pmxcfs/memdb.h
+++ b/src/pmxcfs/memdb.h
@@ -88,6 +88,12 @@ typedef struct {
db_backend_t *bdb;
} memdb_t;
+typedef struct {
+ gboolean in_progress; // whether a backup is currently in progress
+ int remaining; // how many pages are still remaining to back up
+ int total; // how many pages there are to back up in total after the last backup step
+} memdb_backup_progress_t;
+
memdb_t *memdb_open(const char *dbfilename);
void memdb_close(memdb_t *memdb);
@@ -200,6 +206,17 @@ int memdb_finish_or_abort_backup(memdb_t *memdb, gboolean abort);
*/
int memdb_handle_backup(memdb_t *memdb);
+/**
+ * memdb_backup_progress:
+ * @memdb: a memdb object that has an initialized db to back up.
+ *
+ * Queries whether a backup is in progress and if so how far it has progressed.
+ *
+ * Return: the returned `memdb_backup_progress_t` struct provides information on whether a back up
+ * is in progress and if so how far it has progressed.
+ */
+memdb_backup_progress_t memdb_backup_progress(memdb_t *memdb);
+
db_backend_t *bdb_backend_open(const char *filename, memdb_tree_entry_t *root, GHashTable *index);
void bdb_backend_close(db_backend_t *bdb);
@@ -267,4 +284,15 @@ int bdb_finish_or_abort_backup(db_backend_t *bdb, gboolean abort);
*/
int bdb_handle_backup(db_backend_t *bdb);
+/**
+ * bdb_backup_progress:
+ * @bdb: a db backend that has an initialized db to back up.
+ *
+ * Queries whether a backup is in progress and if so how far it has progressed.
+ *
+ * Return: the returned `memdb_backup_progress_t` struct provides information on whether a back up
+ * is in progress and if so how far it has progressed.
+ */
+memdb_backup_progress_t bdb_backup_progress(db_backend_t *bdb);
+
#endif /* _PVE_MEMDB_H_ */
diff --git a/src/pmxcfs/server.c b/src/pmxcfs/server.c
index 8149fd3..5f9ab0a 100644
--- a/src/pmxcfs/server.c
+++ b/src/pmxcfs/server.c
@@ -511,6 +511,9 @@ static int32_t s1_msg_process_fn(qb_ipcs_connection_t *c, void *data, size_t siz
if (result != 0) {
cfs_critical("couldn't add first backup step (error %d), abort...", result);
(void)memdb_finish_or_abort_backup(memdb, TRUE);
+ } else {
+ memdb_backup_progress_t progress = memdb_backup_progress(memdb);
+ cfs_create_backup_progress_msg(outbuf, &progress);
}
}
@@ -522,6 +525,14 @@ static int32_t s1_msg_process_fn(qb_ipcs_connection_t *c, void *data, size_t siz
result = -EINVAL;
}
}
+ } else if (request_id == CFS_IPC_BACKUP_PROGRESS) {
+ if (request_size != sizeof(struct qb_ipc_request_header)) {
+ result = -EINVAL;
+ } else {
+ memdb_backup_progress_t progress = memdb_backup_progress(memdb);
+ cfs_create_backup_progress_msg(outbuf, &progress);
+ result = 0;
+ }
}
cfs_debug("process result %d", result);
diff --git a/src/pmxcfs/status.c b/src/pmxcfs/status.c
index 9581e2a..41591d5 100644
--- a/src/pmxcfs/status.c
+++ b/src/pmxcfs/status.c
@@ -1974,3 +1974,10 @@ void cfs_set_quorate(uint32_t quorate, gboolean quiet) {
g_mutex_unlock(&mutex);
}
+
+void cfs_create_backup_progress_msg(GString *str, memdb_backup_progress_t *progress) {
+ g_string_append_printf(
+ str, "{\n\t\"in-progress\": %s,\n\t\"remaining\": %d,\n\t\"total\": %d\n}",
+ progress->in_progress ? "true" : "false", progress->remaining, progress->total
+ );
+}
diff --git a/src/pmxcfs/status.h b/src/pmxcfs/status.h
index 6a6b0a7..0790c88 100644
--- a/src/pmxcfs/status.h
+++ b/src/pmxcfs/status.h
@@ -103,4 +103,6 @@ int cfs_create_guest_conf_properties_msg(
GString *str, memdb_t *memdb, const char **props, uint8_t num_props, uint32_t vmid
);
+void cfs_create_backup_progress_msg(GString *str, memdb_backup_progress_t *progress);
+
#endif /* _PVE_STATUS_H_ */
--
2.47.3
next prev parent reply other threads:[~2026-08-28 13:31 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 13:30 [RFC cluster/common/container/docs/installer/manager 00/21] add rudimentary host backup mechanism Shannon Sterz
2026-08-28 13:30 ` [PATCH cluster 01/21] pmxcfs: status: fix formatting of parameters in checked_mkdir() Shannon Sterz
2026-08-28 13:30 ` [PATCH cluster 02/21] pmxcfs: correctly log message when directory can't be created Shannon Sterz
2026-08-28 13:30 ` [PATCH cluster 03/21] pmxcfs: add live backup capability Shannon Sterz
2026-08-28 13:30 ` Shannon Sterz [this message]
2026-08-28 13:30 ` [PATCH common 05/21] systemd: move parse_os_release() helper to PVE::Systemd Shannon Sterz
2026-08-28 13:30 ` [PATCH container 06/21] setup: use parse_os_release from PVE::Systemd Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 07/21] jobs/api: add basic host backup job logic Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 08/21] api: cluster: add endpoints for manage host backup jobs Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 09/21] api: node: add endpoints for listing backups for a node Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 10/21] api: host backup: include global, disk and network options for restore Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 11/21] api: host backup: add warnings in case zfs snapdir is disabled Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 12/21] ui: node: add panel to manage backups of a host Shannon Sterz
2026-08-28 13:30 ` [PATCH manager 13/21] ui: dc: add panel for managing host backup jobs Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 14/21] bump proxmox-installer-types to 0.2 Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 15/21] make tidy and clean up whitespace in unconfigured.sh Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 16/21] installer-common: add option to verify TLS connections via callback Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 17/21] low-level-installer: add support for restoring backups Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 18/21] installer-common/tui-installer: implement restore tui Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 19/21] unconfigured: add restore mode to unconfigured.sh Shannon Sterz
2026-08-28 13:30 ` [PATCH installer 20/21] tui-installer: unmount a potentially mounted backup on abort Shannon Sterz
2026-08-28 13:30 ` [PATCH docs 21/21] examples: add example hook script for host backup jobs Shannon Sterz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260828133030.351140-5-s.sterz@proxmox.com \
--to=s.sterz@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.