- util: introduce object for holding a system inhibitor lock (RHEL-83064) - src: convert drivers over to new virInhibitor APIs (RHEL-83064) - rpc: remove logind support for virNetDaemon (RHEL-83064) - util: fix off-by-1 in inhibitor constants (RHEL-83064) - util: don't attempt to acquire logind inhibitor if not requested (RHEL-83064) - network: Free inhibitor in networkStateCleanup() (RHEL-83064) - conf: introduce support for multiple ACPI tables (RHEL-81041) - src: validate permitted ACPI table types in libxl/qemu drivers (RHEL-81041) - src: introduce 'raw' and 'rawset' ACPI table types (RHEL-81041) - qemu: support 'raw' ACPI table type (RHEL-81041) - libxl: support 'rawset' ACPI table type (RHEL-81041) - conf: support MSDM ACPI table type (RHEL-81041) - qemu: support MSDM ACPI table type (RHEL-81041) - qemuxmlconftest: Include shared memory 'net-vhostuser' test cases (RHEL-84133) - qemuValidateDomainDeviceDefNetwork: Require shared memory for all vhost-user interfaces (RHEL-84133) - qemu: process: Remove un-updated 'qemuProcessStartWarnShmem' (RHEL-84133) Resolves: RHEL-81041, RHEL-83064, RHEL-84133
376 lines
11 KiB
Diff
376 lines
11 KiB
Diff
From 4c1429d270836f0e6ab04b052f1184d72d21193c Mon Sep 17 00:00:00 2001
|
|
Message-ID: <4c1429d270836f0e6ab04b052f1184d72d21193c.1742990721.git.jdenemar@redhat.com>
|
|
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
|
Date: Mon, 16 Dec 2024 15:19:34 +0000
|
|
Subject: [PATCH] util: introduce object for holding a system inhibitor lock
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
The system inhibitor locks are currently handled by code in the
|
|
virNetDaemon class. The driver code invokes a callback provided
|
|
by the daemon when it wants to start or end inhibition.
|
|
|
|
When the first inhibition is started, the daemon will call out
|
|
to logind to apply it system wide.
|
|
|
|
This has many flaws
|
|
|
|
* A single message is registered with logind regardless of
|
|
what driver holds the inhibition
|
|
* An inhibition of daemon shutdown can't be acquired
|
|
without also inhibiting system shutdown
|
|
* Config of the inhibitions cannot be tailored by the
|
|
driver
|
|
|
|
The new virInhibitor object addresses these:
|
|
|
|
* The object directly manages an inhibition with logind
|
|
privately to the driver, enabling custom messages to
|
|
be set.
|
|
* It is possible to acquire an inhibition locally to the
|
|
daemon without forwarding it to logind.
|
|
|
|
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
(cherry picked from commit d2e5aa4f4e1501149c9e3095d38ebc04c9a4ba31)
|
|
Resolves: https://issues.redhat.com/browse/RHEL-83064
|
|
---
|
|
po/POTFILES | 1 +
|
|
src/libvirt_private.syms | 7 ++
|
|
src/util/meson.build | 1 +
|
|
src/util/virinhibitor.c | 214 +++++++++++++++++++++++++++++++++++++++
|
|
src/util/virinhibitor.h | 58 +++++++++++
|
|
5 files changed, 281 insertions(+)
|
|
create mode 100644 src/util/virinhibitor.c
|
|
create mode 100644 src/util/virinhibitor.h
|
|
|
|
diff --git a/po/POTFILES b/po/POTFILES
|
|
index 3514aa3dca..c71e439fe3 100644
|
|
--- a/po/POTFILES
|
|
+++ b/po/POTFILES
|
|
@@ -293,6 +293,7 @@ src/util/virhostcpu.c
|
|
src/util/virhostmem.c
|
|
src/util/virhostuptime.c
|
|
src/util/viridentity.c
|
|
+src/util/virinhibitor.c
|
|
src/util/virinitctl.c
|
|
src/util/viriscsi.c
|
|
src/util/virjson.c
|
|
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
index 7d404fdbf5..727ab52cfe 100644
|
|
--- a/src/libvirt_private.syms
|
|
+++ b/src/libvirt_private.syms
|
|
@@ -2605,6 +2605,13 @@ virIdentitySetUserName;
|
|
virIdentitySetX509DName;
|
|
|
|
|
|
+# util/virinhibitor.h
|
|
+virInhibitorFree;
|
|
+virInhibitorHold;
|
|
+virInhibitorNew;
|
|
+virInhibitorRelease;
|
|
+
|
|
+
|
|
# util/virinitctl.h
|
|
virInitctlFifos;
|
|
virInitctlSetRunLevel;
|
|
diff --git a/src/util/meson.build b/src/util/meson.build
|
|
index 30f71b0227..69ef49139a 100644
|
|
--- a/src/util/meson.build
|
|
+++ b/src/util/meson.build
|
|
@@ -45,6 +45,7 @@ util_sources = [
|
|
'virhostmem.c',
|
|
'virhostuptime.c',
|
|
'viridentity.c',
|
|
+ 'virinhibitor.c',
|
|
'virinitctl.c',
|
|
'viriscsi.c',
|
|
'virjson.c',
|
|
diff --git a/src/util/virinhibitor.c b/src/util/virinhibitor.c
|
|
new file mode 100644
|
|
index 0000000000..647bdc9fbb
|
|
--- /dev/null
|
|
+++ b/src/util/virinhibitor.c
|
|
@@ -0,0 +1,214 @@
|
|
+/*
|
|
+ * virinhibitor.c: helper APIs for inhibiting host actions
|
|
+ *
|
|
+ * Copyright (C) 2024 Red Hat, Inc.
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library. If not, see
|
|
+ * <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#include <config.h>
|
|
+
|
|
+#include "virinhibitor.h"
|
|
+#include "virgdbus.h"
|
|
+#include "virsystemd.h"
|
|
+#include "virfile.h"
|
|
+#include "virlog.h"
|
|
+#include "virenum.h"
|
|
+
|
|
+#define VIR_FROM_THIS VIR_FROM_NONE
|
|
+
|
|
+VIR_LOG_INIT("util.inhibitor");
|
|
+
|
|
+struct _virInhibitor {
|
|
+ GMutex lock;
|
|
+ size_t count;
|
|
+ int fd;
|
|
+
|
|
+ char *what;
|
|
+ char *who;
|
|
+ char *why;
|
|
+ const char *mode;
|
|
+
|
|
+ virInhibitorAction action;
|
|
+ void *actionData;
|
|
+};
|
|
+
|
|
+VIR_ENUM_DECL(virInhibitorMode);
|
|
+
|
|
+VIR_ENUM_IMPL(virInhibitorMode,
|
|
+ VIR_INHIBITOR_MODE_LAST,
|
|
+ "block", "delay");
|
|
+
|
|
+#ifdef G_OS_UNIX
|
|
+/* As per: https://www.freedesktop.org/wiki/Software/systemd/inhibit */
|
|
+static int
|
|
+virInhibitorAcquire(const char *what,
|
|
+ const char *who,
|
|
+ const char *why,
|
|
+ const char *mode,
|
|
+ int *inhibitorFD)
|
|
+{
|
|
+ g_autoptr(GVariant) reply = NULL;
|
|
+ g_autoptr(GUnixFDList) replyFD = NULL;
|
|
+ g_autoptr(GVariant) message = NULL;
|
|
+ GDBusConnection *systemBus;
|
|
+ int fd;
|
|
+ int rc;
|
|
+
|
|
+ VIR_DEBUG("what=%s who=%s why=%s mode=%s",
|
|
+ NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
|
|
+
|
|
+ if (!(systemBus = virGDBusGetSystemBus())) {
|
|
+ VIR_DEBUG("system dbus not available, skipping system inhibitor");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (virSystemdHasLogind() < 0) {
|
|
+ VIR_DEBUG("logind not available, skipping system inhibitor");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ message = g_variant_new("(ssss)", what, who, why, mode);
|
|
+
|
|
+ rc = virGDBusCallMethodWithFD(systemBus,
|
|
+ &reply,
|
|
+ G_VARIANT_TYPE("(h)"),
|
|
+ &replyFD,
|
|
+ NULL,
|
|
+ "org.freedesktop.login1",
|
|
+ "/org/freedesktop/login1",
|
|
+ "org.freedesktop.login1.Manager",
|
|
+ "Inhibit",
|
|
+ message,
|
|
+ NULL);
|
|
+
|
|
+ if (rc < 0)
|
|
+ return -1;
|
|
+
|
|
+ if (g_unix_fd_list_get_length(replyFD) <= 0) {
|
|
+ VIR_DEBUG("Missing inhibitor FD in logind reply");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ fd = g_unix_fd_list_get(replyFD, 0, NULL);
|
|
+ if (fd < 0) {
|
|
+ VIR_DEBUG("Unable to get inhibitor FD from logind reply");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ *inhibitorFD = fd;
|
|
+ VIR_DEBUG("Got inhibitor FD %d", fd);
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
+static char *
|
|
+virInhibitorWhatFormat(virInhibitorWhat what)
|
|
+{
|
|
+ const char *whatstr[] = {
|
|
+ "sleep",
|
|
+ "shutdown",
|
|
+ "idle",
|
|
+ "handle-power-key",
|
|
+ "handle-suspend-key",
|
|
+ "handle-hibernate-key",
|
|
+ "handle-lid-switch",
|
|
+ };
|
|
+ GString *str = g_string_new("");
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < G_N_ELEMENTS(whatstr); i++) {
|
|
+ if (what & (1 << i)) {
|
|
+ if (str->len)
|
|
+ g_string_append(str, ":");
|
|
+ g_string_append(str, whatstr[i]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return g_string_free(str, FALSE);
|
|
+}
|
|
+
|
|
+
|
|
+virInhibitor *virInhibitorNew(virInhibitorWhat what,
|
|
+ const char *who,
|
|
+ const char *why,
|
|
+ virInhibitorMode mode,
|
|
+ virInhibitorAction action,
|
|
+ void *actionData)
|
|
+{
|
|
+ virInhibitor *inhibitor = g_new0(virInhibitor, 1);
|
|
+
|
|
+ inhibitor->fd = -1;
|
|
+ inhibitor->what = virInhibitorWhatFormat(what);
|
|
+ inhibitor->who = g_strdup(who);
|
|
+ inhibitor->why = g_strdup(why);
|
|
+ inhibitor->mode = virInhibitorModeTypeToString(mode);
|
|
+ inhibitor->action = action;
|
|
+ inhibitor->actionData = actionData;
|
|
+
|
|
+ return inhibitor;
|
|
+}
|
|
+
|
|
+void virInhibitorHold(virInhibitor *inhibitor)
|
|
+{
|
|
+ g_mutex_lock(&inhibitor->lock);
|
|
+
|
|
+ if (inhibitor->count == 0) {
|
|
+ if (inhibitor->action) {
|
|
+ inhibitor->action(true, inhibitor->actionData);
|
|
+ }
|
|
+#ifdef G_OS_UNIX
|
|
+ if (virInhibitorAcquire(
|
|
+ inhibitor->what, inhibitor->who, inhibitor->why,
|
|
+ inhibitor->mode, &inhibitor->fd) < 0) {
|
|
+ VIR_ERROR(_("Failed to acquire inhibitor: %1$s"),
|
|
+ virGetLastErrorMessage());
|
|
+ virResetLastError();
|
|
+ }
|
|
+#else
|
|
+ VIR_DEBUG("No inhibitor implementation on non-UNIX platforms");
|
|
+#endif
|
|
+ }
|
|
+ inhibitor->count++;
|
|
+ g_mutex_unlock(&inhibitor->lock);
|
|
+}
|
|
+
|
|
+
|
|
+void virInhibitorRelease(virInhibitor *inhibitor)
|
|
+{
|
|
+ g_mutex_lock(&inhibitor->lock);
|
|
+ inhibitor->count--;
|
|
+ if (inhibitor->count == 0) {
|
|
+ VIR_FORCE_CLOSE(inhibitor->fd);
|
|
+ if (inhibitor->action) {
|
|
+ inhibitor->action(false, inhibitor->actionData);
|
|
+ }
|
|
+ }
|
|
+ g_mutex_unlock(&inhibitor->lock);
|
|
+}
|
|
+
|
|
+
|
|
+void virInhibitorFree(virInhibitor *inhibitor)
|
|
+{
|
|
+ if (!inhibitor)
|
|
+ return;
|
|
+
|
|
+ g_free(inhibitor->what);
|
|
+ g_free(inhibitor->who);
|
|
+ g_free(inhibitor->why);
|
|
+ VIR_FORCE_CLOSE(inhibitor->fd);
|
|
+ g_free(inhibitor);
|
|
+}
|
|
diff --git a/src/util/virinhibitor.h b/src/util/virinhibitor.h
|
|
new file mode 100644
|
|
index 0000000000..0a1c445d41
|
|
--- /dev/null
|
|
+++ b/src/util/virinhibitor.h
|
|
@@ -0,0 +1,58 @@
|
|
+/*
|
|
+ * virinhibitor.h: helper APIs for inhibiting host actions
|
|
+ *
|
|
+ * Copyright (C) 2024 Red Hat, Inc.
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library. If not, see
|
|
+ * <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "internal.h"
|
|
+
|
|
+typedef struct _virInhibitor virInhibitor;
|
|
+
|
|
+typedef enum {
|
|
+ VIR_INHIBITOR_WHAT_NONE = 0,
|
|
+ VIR_INHIBITOR_WHAT_SLEEP = (1 << 1),
|
|
+ VIR_INHIBITOR_WHAT_SHUTDOWN = (1 << 2),
|
|
+ VIR_INHIBITOR_WHAT_IDLE = (1 << 3),
|
|
+ VIR_INHIBITOR_WHAT_POWER_KEY = (1 << 4),
|
|
+ VIR_INHIBITOR_WHAT_SUSPEND_KEY = (1 << 5),
|
|
+ VIR_INHIBITOR_WHAT_HIBERNATE_KEY = (1 << 6),
|
|
+ VIR_INHIBITOR_WHAT_LID_SWITCH = (1 << 7),
|
|
+} virInhibitorWhat;
|
|
+
|
|
+typedef enum {
|
|
+ VIR_INHIBITOR_MODE_BLOCK,
|
|
+ VIR_INHIBITOR_MODE_DELAY,
|
|
+
|
|
+ VIR_INHIBITOR_MODE_LAST
|
|
+} virInhibitorMode;
|
|
+
|
|
+typedef void (*virInhibitorAction)(bool inhibited,
|
|
+ void *opaque);
|
|
+
|
|
+virInhibitor *virInhibitorNew(virInhibitorWhat what,
|
|
+ const char *who,
|
|
+ const char *why,
|
|
+ virInhibitorMode mode,
|
|
+ virInhibitorAction action,
|
|
+ void *actionData);
|
|
+
|
|
+void virInhibitorHold(virInhibitor *inhibitor);
|
|
+void virInhibitorRelease(virInhibitor *inhibitor);
|
|
+
|
|
+void virInhibitorFree(virInhibitor *inhibitor);
|
|
--
|
|
2.49.0
|