From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 4C87E1FF0C2 for ; Thu, 22 Oct 2026 15:12:57 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id A95C121756; Thu, 22 Oct 2026 15:12:54 +0200 (CEST) Date: Thu, 22 Oct 2026 15:12:49 +0200 From: Wolfgang Bumiller To: Shannon Sterz Subject: Re: [PATCH cluster 04/21] pmxcfs: add ability to query backup progress Message-ID: References: <20260828133030.351140-1-s.sterz@proxmox.com> <20260828133030.351140-5-s.sterz@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260828133030.351140-5-s.sterz@proxmox.com> X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792674769691 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.403 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: AHFHGCHZ7KINOUVOZPC3Z5KZXOTORGQV X-Message-ID-Hash: AHFHGCHZ7KINOUVOZPC3Z5KZXOTORGQV X-MailFrom: w.bumiller@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: pve-devel@lists.proxmox.com X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: On Fri, Aug 28, 2026 at 03:30:13PM +0200, Shannon Sterz wrote: > cfs_live_backup_database() will now also return the progress of the > backup instead of just the filename. > > Signed-off-by: Shannon Sterz > --- > 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; (Should the previous patch already use `die` here?) > + > + 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 is the filename of the new backups and > +C which is also a hash. C has three members: C, > +a boolean indicating whether the backup is finished or still on-going, > +C, an integer showing the pages that are not yet backed up, and > +C 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, a boolean indicating whether the > +backup is finished or still on-going, C, an integer showing the pages > +that are not yet backed up, and C 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 > > > > > --