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 D762C1FF195 for ; Thu, 22 Oct 2026 18:16:26 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 529CE21622; Thu, 22 Oct 2026 18:16:26 +0200 (CEST) From: Jonas Theisen To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup] api: gc status: pass schedule instead of UPID to schedule helper Date: Thu, 22 Oct 2026 18:15:49 +0200 Message-ID: <20261022161612.331793-1-j.theisen@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792685780889 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.125 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: 6ERESSZFL556NTF7FDXJ6PGUGZ6AV2FB X-Message-ID-Hash: 6ERESSZFL556NTF7FDXJ6PGUGZ6AV2FB X-MailFrom: j.theisen@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 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Since the GC job status was introduced and then refactored in [1] the last GC run's UPID has been passed as the schedule argument of compute_schedule_status(). A UPID never parses as a calendar event, so the computed next run was always None, and it was then recomputed from the GC schedule in a separate step after the fact. Pass the configured GC schedule instead and use the helper's result directly. This drops the duplicated computation, and the next run of GC jobs is now derived from the job state file in the same way as for sync, verify, prune and tape backup jobs. Previously, the base was the last run's end time from the in-memory GC status, or the current time if there was none, which ignored the job state that the proxy's scheduler relies on. [1] https://lore.proxmox.com/pbs-devel/20260319110318.70346-2-m.koeppl@proxmox.com/ Signed-off-by: Jonas Theisen --- src/api2/admin/datastore.rs | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 3367fb2c1..cfe976811 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -29,7 +29,6 @@ use proxmox_rrd_api_types::{RrdMode, RrdTimeframe}; use proxmox_schema::*; use proxmox_sortable_macro::sortable; use proxmox_sys::fs::{CreateOptions, file_read_firstline, file_read_optional_string}; -use proxmox_time::CalendarEvent; use proxmox_worker_task::WorkerTaskContext; use pxar::EntryKind; @@ -1270,42 +1269,21 @@ pub(crate) fn garbage_collection_status_unchecked( let datastore = DataStore::lookup_datastore(lookup_with(&store, Operation::Read))?; let status_in_memory = datastore.last_gc_status(); - let mut last = proxmox_time::epoch_i64(); - - let jobtype = "garbage_collection"; + let computed_schedule: JobScheduleStatus = + compute_schedule_status("garbage_collection", &store, info.schedule.as_deref())?; if let Some(ref upid) = status_in_memory.upid { - let computed_schedule: JobScheduleStatus = - compute_schedule_status(jobtype, &store, Some(upid))?; - if let Some(endtime) = computed_schedule.last_run_endtime { - last = endtime; if let Ok(parsed_upid) = upid.parse::() { info.duration = Some(endtime - parsed_upid.starttime); } } - info.next_run = computed_schedule.next_run; info.last_run_endtime = computed_schedule.last_run_endtime; info.last_run_state = computed_schedule.last_run_state; - } else if let Err(err) = JobState::load(jobtype, &store) { - log::error!("could not open statefile for {store}: {err}"); } - info.next_run = info - .schedule - .as_ref() - .and_then(|s| { - s.parse::() - .map_err(|err| log::error!("{err}")) - .ok() - }) - .and_then(|e| { - e.compute_next_event(last) - .map_err(|err| log::error!("{err}")) - .ok() - }) - .and_then(|ne| ne); + info.next_run = computed_schedule.next_run; info.status = status_in_memory; -- 2.47.3