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 71B521FF0C1 for ; Fri, 18 Sep 2026 16:43:04 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id A86DD21680; Fri, 18 Sep 2026 16:42:15 +0200 (CEST) From: Hannes Laimer To: pve-devel@lists.proxmox.com Subject: [PATCH pve-cluster 06/10] pmxcfs: notify: emit change events over the notification socket Date: Fri, 18 Sep 2026 16:41:48 +0200 Message-ID: <20260918144152.575163-7-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260918144152.575163-1-h.laimer@proxmox.com> References: <20260918144152.575163-1-h.laimer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1789742529466 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.488 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 RCVD_IN_MSPIKE_H2 0.001 Average reputation (+2) 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: BYTKXHTC5XTUJHPXT4N3NDVIZPB4CSEQ X-Message-ID-Hash: BYTKXHTC5XTUJHPXT4N3NDVIZPB4CSEQ X-MailFrom: h.laimer@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 VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Start the notification socket after the daemonize fork and before any thread can mutate the tree, with the memdb hook installed and the version of the last mutation so far handed over. That way no change slips past the socket while it comes up, and a client resuming at that version after a restart is current and needs no resync. A failure to bring the socket up is logged and the daemon carries on. Messages from the notifier are routed through the daemon's own logging under a dedicated domain so they end up in the same journal stream as everything else. Signed-off-by: Hannes Laimer --- src/pmxcfs/cfs-utils.h | 4 ++++ src/pmxcfs/pmxcfs.c | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/pmxcfs/cfs-utils.h b/src/pmxcfs/cfs-utils.h index ed67264..29f844e 100644 --- a/src/pmxcfs/cfs-utils.h +++ b/src/pmxcfs/cfs-utils.h @@ -78,6 +78,10 @@ void ipc_log_fn(const char *file, int32_t line, int32_t severity, const char *ms cfs_log(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, __FILE__, __LINE__, G_STRFUNC, __VA_ARGS__) #define cfs_dom_critical(domain, ...) \ cfs_log(domain, G_LOG_LEVEL_CRITICAL, __FILE__, __LINE__, G_STRFUNC, __VA_ARGS__) +#define cfs_warn(...) \ + cfs_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, __FILE__, __LINE__, G_STRFUNC, __VA_ARGS__) +#define cfs_dom_warn(domain, ...) \ + cfs_log(domain, G_LOG_LEVEL_WARNING, __FILE__, __LINE__, G_STRFUNC, __VA_ARGS__) #define cfs_message(...) \ cfs_log(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, __FILE__, __LINE__, G_STRFUNC, __VA_ARGS__) #define cfs_dom_message(domain, ...) \ diff --git a/src/pmxcfs/pmxcfs.c b/src/pmxcfs/pmxcfs.c index 14f1168..575ea3a 100644 --- a/src/pmxcfs/pmxcfs.c +++ b/src/pmxcfs/pmxcfs.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ #include "confdb.h" #include "dcdb.h" #include "dfsm.h" +#include "pmxcfs-notify.h" #include "quorum.h" #include "server.h" #include "status.h" @@ -58,6 +60,7 @@ #define DBFILENAME VARLIBDIR "/config.db" #define LOCKFILE VARLIBDIR "/.pmxcfs.lockfile" #define RESTART_FLAG_FILE RUNDIR "/cfs-restart-flag" +#define NOTIFY_SOCKET RUNDIR "/pmxcfs.sock" #define CFSDIR "/etc/pve" @@ -78,6 +81,18 @@ static void glib_log_handler( cfs_log(log_domain, log_level, NULL, 0, NULL, "%s", message); } +static void notify_log_cb(int priority, const char *msg) { + if (priority <= LOG_ERR) { + cfs_dom_critical("notify", "%s", msg); + } else if (priority <= LOG_WARNING) { + cfs_dom_warn("notify", "%s", msg); + } else if (priority <= LOG_INFO) { + cfs_dom_message("notify", "%s", msg); + } else { + cfs_dom_debug("notify", "%s", msg); + } +} + static gboolean write_pidfile(pid_t pid) { char *strpid = g_strdup_printf("%d\n", pid); gboolean res = atomic_write_file(CFS_PID_FN, strpid, strlen(strpid), 0644, getgid()); @@ -1032,6 +1047,14 @@ int main(int argc, char *argv[]) { cfs_loop_add_service(corosync_loop, service_status, QB_LOOP_LOW); } + memdb_set_notify_hook(pmxcfs_notify_emit); + + // brought up before any thread can mutate the tree, so the version it is + // handed is exact and no change slips past it while it comes up + if (pmxcfs_notify_init(NOTIFY_SOCKET, cfs.gid, notify_log_cb, memdb->root->version) != 0) { + cfs_critical("running without change notification socket"); + } + cfs_loop_start_worker(corosync_loop); server_start(memdb); @@ -1053,6 +1076,8 @@ int main(int argc, char *argv[]) { server_stop(); + pmxcfs_notify_shutdown(); + fuse_unmount(CFSDIR, fuse_chan); fuse_destroy(fuse); -- 2.47.3