Pull in latest udev rules and race fixes for handling udev rules

Related: #2060793
This commit is contained in:
Ray Strode 2022-03-07 10:22:46 -05:00
parent 7c05e20e13
commit 1054e3fbf5
6 changed files with 1412 additions and 61 deletions

View File

@ -1,58 +0,0 @@
From db206f3b4626dda65cf5517d2ae1ab633d791fef Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 11 Feb 2019 18:14:07 -0500
Subject: [PATCH] data: disable wayland on certain hardware
We're having issues with wayland on passthrough to virt
setups and with the vendor nvidia driver on hybrid graphics
setups, so disable it in those cases.
---
data/61-gdm.rules.in | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index b1da191f8..d863a4a4d 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,6 +1,34 @@
# disable Wayland on Hi1710 chipsets
-ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
-# disable Wayland when using the proprietary nvidia driver
-DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+
+# disable Wayland on Matrox chipsets
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+
+# disable Wayland on aspeed chipsets
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+
+# disable Wayland on hybrid systems with vendor nvidia driver
+# default to Xorg on single gpu vendor nvidia systems
+DRIVER=="nvidia", ENV{GDM_HAS_VENDOR_NVIDIA_DRIVER}="1"
+DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg"
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_NVIDIA_DRIVER}=="1", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nvidia_drm", ATTR{parameters/modeset}=="N", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+
+# disable Wayland on passthrough graphics setups for now (assumes passthrough if
+# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl)
+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_VIRTUAL_GPU}=="1", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+
# disable Wayland if modesetting is disabled
-IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
--
2.31.1

View File

@ -0,0 +1,725 @@
From e5b3467412874d27c311253e3d5d7e65a61d12a4 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 1 Mar 2022 13:25:02 -0500
Subject: [PATCH 1/4] local-display-factory: Stall startup until main graphics
card is ready
At the moment, GDM waits until systemd says the system supports
graphics (via the CanGraphical logind property).
Unfortunately, this property isn't really what we need, since it flips
to true when *any* graphics are available, not when the main graphics
for the system are ready.
This is a problem on hybrid graphics systems, if one card is slower to
load than another. In particular, the vendor nvidia driver can be slow
to load because it has multiple kernel modules it loads in series.
Indeed on fast systems, that use the vendor nvidia driver, it's not
unusual for boot to get to a point where all of userspace up to and
including GDM is executed before the graphics are ready to go.
This commit tries to mitigate the situation by adding an additional,
check aside from CanGraphical to test if the system is ready.
This check waits for the graphics card associated with boot to be fully
up and running before proceeding to start a login screen.
Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/763
---
daemon/gdm-local-display-factory.c | 164 ++++++++++++++++++++++++++---
daemon/meson.build | 4 +
meson.build | 2 +
4 files changed, 159 insertions(+), 12 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index c00e1c47..0b1d3482 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1,100 +1,112 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gio/gio.h>
+#ifdef HAVE_UDEV
+#include <gudev/gudev.h>
+#endif
+
#include <systemd/sd-login.h>
#include "gdm-common.h"
#include "gdm-manager.h"
#include "gdm-display-factory.h"
#include "gdm-local-display-factory.h"
#include "gdm-local-display-factory-glue.h"
#include "gdm-settings-keys.h"
#include "gdm-settings-direct.h"
#include "gdm-display-store.h"
#include "gdm-local-display.h"
#include "gdm-legacy-display.h"
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
#define MAX_DISPLAY_FAILURES 5
#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
#define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */
struct _GdmLocalDisplayFactory
{
- GdmDisplayFactory parent;
+ GdmDisplayFactory parent;
+#ifdef HAVE_UDEV
+ GUdevClient *gudev_client;
+#endif
GdmDBusLocalDisplayFactory *skeleton;
GDBusConnection *connection;
GHashTable *used_display_numbers;
/* FIXME: this needs to be per seat? */
guint num_failures;
guint seat_new_id;
guint seat_removed_id;
guint seat_properties_changed_id;
+ gboolean seat0_has_platform_graphics;
+ gboolean seat0_has_boot_up_graphics;
+
gboolean seat0_graphics_check_timed_out;
guint seat0_graphics_check_timeout_id;
+ guint uevent_handler_id;
+
#if defined(ENABLE_USER_DISPLAY_SERVER)
unsigned int active_vt;
guint active_vt_watch_id;
guint wait_to_finish_timeout_id;
#endif
gboolean is_started;
};
enum {
PROP_0,
};
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
static void gdm_local_display_factory_finalize (GObject *object);
static void ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id);
static void on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory);
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
static gpointer local_display_factory_object = NULL;
static gboolean lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data);
@@ -594,142 +606,232 @@ lookup_by_seat_id (const char *id,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static gboolean
lookup_prepared_display_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
int status;
status = gdm_display_get_status (display);
if (status != GDM_DISPLAY_PREPARED)
return FALSE;
return lookup_by_seat_id (id, display, user_data);
}
+#ifdef HAVE_UDEV
+static gboolean
+udev_is_settled (GdmLocalDisplayFactory *factory)
+{
+ g_autoptr (GUdevEnumerator) enumerator = NULL;
+ GList *devices;
+ GList *node;
+
+ gboolean is_settled = FALSE;
+
+ if (factory->seat0_has_platform_graphics) {
+ g_debug ("GdmLocalDisplayFactory: udev settled, platform graphics enabled.");
+ return TRUE;
+ }
+
+ if (factory->seat0_has_boot_up_graphics) {
+ g_debug ("GdmLocalDisplayFactory: udev settled, boot up graphics available.");
+ return TRUE;
+ }
+
+ if (factory->seat0_graphics_check_timed_out) {
+ g_debug ("GdmLocalDisplayFactory: udev timed out, proceeding anyway.");
+ return TRUE;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: Checking if udev has settled enough to support graphics.");
+
+ enumerator = g_udev_enumerator_new (factory->gudev_client);
+
+ g_udev_enumerator_add_match_name (enumerator, "card*");
+ g_udev_enumerator_add_match_tag (enumerator, "master-of-seat");
+ g_udev_enumerator_add_match_subsystem (enumerator, "drm");
+
+ devices = g_udev_enumerator_execute (enumerator);
+ if (!devices) {
+ g_debug ("GdmLocalDisplayFactory: udev has no candidate graphics devices available yet.");
+ return FALSE;
+ }
+
+ node = devices;
+ while (node != NULL) {
+ GUdevDevice *device = node->data;
+ GList *next_node = node->next;
+ g_autoptr (GUdevDevice) platform_device = NULL;
+ g_autoptr (GUdevDevice) pci_device = NULL;
+
+ platform_device = g_udev_device_get_parent_with_subsystem (device, "platform", NULL);
+
+ if (platform_device != NULL) {
+ g_debug ("GdmLocalDisplayFactory: Found embedded platform graphics, proceeding.");
+ factory->seat0_has_platform_graphics = TRUE;
+ is_settled = TRUE;
+ break;
+ }
+
+ pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL);
+
+ if (pci_device != NULL) {
+ gboolean boot_vga;
+
+ boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga");
+
+ if (boot_vga == 1) {
+ g_debug ("GdmLocalDisplayFactory: Found primary PCI graphics adapter, proceeding.");
+ factory->seat0_has_boot_up_graphics = TRUE;
+ is_settled = TRUE;
+ break;
+ } else {
+ g_debug ("GdmLocalDisplayFactory: Found secondary PCI graphics adapter, not proceeding yet.");
+ }
+ }
+ node = next_node;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: udev has %ssettled enough for graphics.", is_settled? "" : "not ");
+ g_list_free_full (devices, g_object_unref);
+ return is_settled;
+}
+#endif
+
static int
on_seat0_graphics_check_timeout (gpointer user_data)
{
GdmLocalDisplayFactory *factory = user_data;
factory->seat0_graphics_check_timeout_id = 0;
/* Simply try to re-add seat0. If it is there already (i.e. CanGraphical
* turned TRUE, then we'll find it and it will not be created again).
*/
factory->seat0_graphics_check_timed_out = TRUE;
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_REMOVE;
}
static void
ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id)
{
int ret;
gboolean seat_supports_graphics;
gboolean is_seat0;
g_auto (GStrv) session_types = NULL;
const char *legacy_session_types[] = { "x11", NULL };
GdmDisplayStore *store;
GdmDisplay *display = NULL;
g_autofree char *login_session_id = NULL;
gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
g_autofree gchar *preferred_display_server = NULL;
gboolean falling_back = FALSE;
+ gboolean waiting_on_udev = FALSE;
gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
preferred_display_server = get_preferred_display_server (factory);
if (g_strcmp0 (preferred_display_server, "none") == 0) {
g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
return;
}
- ret = sd_seat_can_graphical (seat_id);
+#ifdef HAVE_UDEV
+ waiting_on_udev = !udev_is_settled (factory);
+#endif
- if (ret < 0) {
- g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
- return;
- }
+ if (!waiting_on_udev) {
+ ret = sd_seat_can_graphical (seat_id);
- if (ret == 0) {
- g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
- seat_supports_graphics = FALSE;
+ if (ret < 0) {
+ g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
+ return;
+ }
+
+ if (ret == 0) {
+ g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
+ seat_supports_graphics = FALSE;
+ } else {
+ g_debug ("GdmLocalDisplayFactory: System supports graphics");
+ seat_supports_graphics = TRUE;
+ }
} else {
- g_debug ("GdmLocalDisplayFactory: System supports graphics");
- seat_supports_graphics = TRUE;
+ g_debug ("GdmLocalDisplayFactory: udev is still settling, so not creating display yet");
+ seat_supports_graphics = FALSE;
}
if (g_strcmp0 (seat_id, "seat0") == 0) {
is_seat0 = TRUE;
falling_back = factory->num_failures > 0;
session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
if (session_types == NULL) {
g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
seat_supports_graphics = FALSE;
} else {
g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
session_types[0], falling_back? " fallback" : "");
}
} else {
is_seat0 = FALSE;
g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
/* Force legacy X11 for all auxiliary seats */
seat_supports_graphics = TRUE;
session_types = g_strdupv ((char **) legacy_session_types);
}
/* For seat0, we have a fallback logic to still try starting it after
* SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if
- * CanGraphical is unset.
+ * CanGraphical is unset or udev otherwise never finds a suitable graphics card.
* This is ugly, but it means we'll come up eventually in some
* scenarios where no master device is present.
* Note that we'll force an X11 fallback even though there might be
* cases where an wayland capable device is present and simply not marked as
* master-of-seat. In these cases, this should likely be fixed in the
* udev rules.
*
* At the moment, systemd always sets CanGraphical for non-seat0 seats.
* This is because non-seat0 seats are defined by having master-of-seat
* set. This means we can avoid the fallback check for non-seat0 seats,
* which simplifies the code.
*/
if (is_seat0) {
if (!seat_supports_graphics) {
if (!factory->seat0_graphics_check_timed_out) {
if (factory->seat0_graphics_check_timeout_id == 0) {
g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT);
factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT,
on_seat0_graphics_check_timeout,
factory);
} else {
/* It is not yet time to force X11 fallback. */
g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout.");
}
return;
}
g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!");
@@ -1138,113 +1240,151 @@ on_vt_changed (GIOChannel *source,
if (factory->wait_to_finish_timeout_id != 0) {
g_debug ("GdmLocalDisplayFactory: deferring previous login screen clean up operation");
g_source_remove (factory->wait_to_finish_timeout_id);
}
factory->wait_to_finish_timeout_id = g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
(GSourceFunc)
on_finish_waiting_for_seat0_displays_timeout,
factory);
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
if (factory->active_vt != GDM_INITIAL_VT) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_CONTINUE;
}
#endif
+#ifdef HAVE_UDEV
+static void
+on_uevent (GUdevClient *client,
+ const char *action,
+ GUdevDevice *device,
+ GdmLocalDisplayFactory *factory)
+{
+ if (!g_udev_device_get_device_file (device))
+ return;
+
+ if (g_strcmp0 (action, "add") != 0 &&
+ g_strcmp0 (action, "change") != 0)
+ return;
+
+ if (!udev_is_settled (factory))
+ return;
+
+ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
+ factory->uevent_handler_id = 0;
+
+ ensure_display_for_seat (factory, "seat0");
+}
+#endif
+
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
+ const char *subsystems[] = { "drm", NULL };
factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
factory->seat_removed_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatRemoved",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_removed,
g_object_ref (factory),
g_object_unref);
factory->seat_properties_changed_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.freedesktop.login1.Seat",
G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE,
on_seat_properties_changed,
g_object_ref (factory),
g_object_unref);
+#ifdef HAVE_UDEV
+ factory->gudev_client = g_udev_client_new (subsystems);
+ factory->uevent_handler_id = g_signal_connect (factory->gudev_client,
+ "uevent",
+ G_CALLBACK (on_uevent),
+ factory);
+#endif
#if defined(ENABLE_USER_DISPLAY_SERVER)
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
if (io_channel != NULL) {
factory->active_vt_watch_id =
g_io_add_watch (io_channel,
G_IO_PRI,
(GIOFunc)
on_vt_changed,
factory);
}
#endif
}
static void
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
{
+ if (factory->uevent_handler_id) {
+ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
+ factory->uevent_handler_id = 0;
+ }
+ g_clear_object (&factory->gudev_client);
+
if (factory->seat_new_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_new_id);
factory->seat_new_id = 0;
}
if (factory->seat_removed_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_removed_id);
factory->seat_removed_id = 0;
}
if (factory->seat_properties_changed_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_properties_changed_id);
factory->seat_properties_changed_id = 0;
}
#if defined(ENABLE_USER_DISPLAY_SERVER)
if (factory->active_vt_watch_id) {
g_source_remove (factory->active_vt_watch_id);
factory->active_vt_watch_id = 0;
}
if (factory->wait_to_finish_timeout_id != 0) {
g_source_remove (factory->wait_to_finish_timeout_id);
factory->wait_to_finish_timeout_id = 0;
}
#endif
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
diff --git a/daemon/meson.build b/daemon/meson.build
index 2e61b644..41f30abe 100644
--- a/daemon/meson.build
+++ b/daemon/meson.build
@@ -177,37 +177,41 @@ gdm_daemon_sources = files(
'gdm-session-record.c',
'gdm-session-worker-common.c',
'gdm-session-worker-job.c',
'gdm-session.c',
'main.c',
)
gdm_daemon_gen_sources = [
display_dbus_gen,
local_display_factory_dbus_gen,
manager_dbus_gen,
local_display_dbus_gen,
session_dbus_gen,
session_worker_dbus_gen,
gdm_session_enums,
]
if xdmcp_dep.found()
gdm_daemon_deps += xdmcp_dep
gdm_daemon_sources = [
gdm_daemon_sources,
files(
'gdm-xdmcp-display-factory.c',
'gdm-xdmcp-display.c',
'gdm-xdmcp-chooser-display.c',
),
]
endif
+if gudev_dep.found()
+ gdm_daemon_deps += gudev_dep
+endif
+
gdm_daemon = executable('gdm',
[ gdm_daemon_sources, gdm_daemon_gen_sources ],
dependencies: gdm_daemon_deps,
include_directories: config_h_dir,
install: true,
install_dir: get_option('sbindir')
)
diff --git a/meson.build b/meson.build
index 02d609dc..05d8da41 100644
--- a/meson.build
+++ b/meson.build
@@ -11,60 +11,61 @@ i18n = import('i18n')
# Compiler
cc = meson.get_compiler('c')
# Options
gdm_prefix = get_option('prefix')
gdmconfdir = (get_option('sysconfsubdir') == '')? gdm_prefix / get_option('sysconfdir') : gdm_prefix / get_option('sysconfdir') / get_option('sysconfsubdir')
dmconfdir = (get_option('dmconfdir') != '')? get_option('dmconfdir') : gdm_prefix / get_option('sysconfdir') / 'dm'
udev_dir = get_option('udev-dir')
at_spi_registryd_dir = (get_option('at-spi-registryd-dir') != '')? get_option('at-spi-registryd-dir') : gdm_prefix / get_option('libexecdir')
lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gdm_prefix / get_option('sysconfdir') / 'locale.conf'
pam_mod_dir = (get_option('pam-mod-dir') != '')? get_option('pam-mod-dir') : gdm_prefix / get_option('libdir') / 'security'
dbus_sys_dir = (get_option('dbus-sys') != '')? get_option('dbus-sys') : get_option('sysconfdir') / 'dbus-1' / 'system.d'
gdm_defaults_conf = (get_option('defaults-conf') != '')? get_option('defaults-conf') : gdm_prefix / get_option('datadir') / 'gdm' / 'defaults.conf'
gdm_custom_conf = (get_option('custom-conf') != '')? get_option('custom-conf') : gdmconfdir / 'custom.conf'
gnome_settings_daemon_dir = (get_option('gnome-settings-daemon-dir') != '')? get_option('gnome-settings-daemon-dir') : gdm_prefix / get_option('libexecdir')
gdm_run_dir = (get_option('run-dir') != '')? get_option('run-dir') : gdm_prefix / get_option('localstatedir') / 'run' / 'gdm'
gdm_runtime_conf = (get_option('runtime-conf') != '')? get_option('runtime-conf') : gdm_run_dir / 'custom.conf'
gdm_pid_file = (get_option('pid-file') != '')? get_option('pid-file') : gdm_run_dir / 'gdm.pid'
ran_once_marker_dir = (get_option('ran-once-marker-dir') != '')? get_option('ran-once-marker-dir') : gdm_run_dir
working_dir = (get_option('working-dir') != '')? get_option('working-dir') : gdm_prefix / get_option('localstatedir') / 'lib' / 'gdm'
gdm_xauth_dir = (get_option('xauth-dir') != '')? get_option('xauth-dir') : gdm_run_dir
gdm_screenshot_dir = (get_option('screenshot-dir') != '')? get_option('screenshot-dir') : gdm_run_dir / 'greeter'
# Common variables
config_h_dir = include_directories('.')
# Dependencies
udev_dep = dependency('udev')
+gudev_dep = dependency('gudev-1.0', version: '>= 232')
glib_min_version = '2.56.0'
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1')
libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4')
accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35')
xcb_dep = dependency('xcb')
keyutils_dep = dependency('libkeyutils', required: false)
libselinux_dep = dependency('libselinux', required: get_option('selinux'))
# udev
if udev_dir == ''
if udev_dep.found()
udev_prefix = udev_dep.get_pkgconfig_variable('udevdir')
else
udev_prefix = gdm_prefix / 'lib' / 'udev'
endif
udev_dir = udev_prefix / 'rules.d'
endif
# X11
x_deps = declare_dependency(
dependencies: [
dependency('x11'),
dependency('xau'),
],
@@ -217,60 +218,61 @@ conf.set('HAVE_UTMP_H', have_utmp_header)
conf.set('HAVE_UTMPX_H', have_utmpx_header)
conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r)
conf.set('UTMP', utmp_struct)
conf.set('HAVE_GETUTXENT', cc.has_function('getutxent'))
conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp'))
conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx'))
conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil'))
conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil'))
conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil'))
conf.set('HAVE_PAM_SYSLOG', have_pam_syslog)
conf.set('HAVE_KEYUTILS', keyutils_dep.found())
conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported)
conf.set('HAVE_SELINUX', libselinux_dep.found())
conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen)
conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server'))
conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal'))
conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support'))
conf.set('ENABLE_PROFILING', get_option('profiling'))
conf.set('GDM_INITIAL_VT', get_option('initial-vt'))
conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf)
conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf)
conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf)
conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path'))
conf.set_quoted('GDM_USERNAME', get_option('user'))
conf.set_quoted('GDM_GROUPNAME', get_option('group'))
conf.set('HAVE_LIBXDMCP', xdmcp_dep.found())
conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server)
conf.set('WITH_PLYMOUTH', plymouth_dep.found())
conf.set_quoted('X_SERVER', x_bin)
conf.set_quoted('X_PATH', x_path)
+conf.set('HAVE_UDEV', gudev_dep.found())
conf.set('HAVE_UT_UT_HOST', utmp_has_host_field)
conf.set('HAVE_UT_UT_PID', utmp_has_pid_field)
conf.set('HAVE_UT_UT_ID', utmp_has_id_field)
conf.set('HAVE_UT_UT_NAME', utmp_has_name_field)
conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field)
conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field)
conf.set('HAVE_UT_UT_USER', utmp_has_user_field)
conf.set('HAVE_UT_UT_TIME', utmp_has_time_field)
conf.set('HAVE_UT_UT_TV', utmp_has_tv_field)
conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field)
conf.set('ENABLE_IPV6', get_option('ipv6'))
configure_file(output: 'config.h', configuration: conf)
# Subdirs
subdir('data')
subdir('common')
if pam_extensions_supported
subdir('pam-extensions')
endif
subdir('daemon')
subdir('libgdm')
subdir('utils')
subdir('pam_gdm')
subdir('po')
if libcheck_dep.found()
subdir('tests')
endif
if xdmcp_dep.found()
subdir('chooser')
endif
--
2.34.1

View File

@ -0,0 +1,356 @@
From d3e073fa1cd314b344db1ec22f0add2702a6c299 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Feb 2022 14:33:22 -0500
Subject: [PATCH 2/4] common: Add API to reload settings from disk
Ideally we would reread /run/gdm/custom.conf after we've decided
graphics setup is complete. This is because the file may not
get written out by udev until after GDM is already started and waiting.
As a first step to get there, this commit adds an API for rereading
the file, and changes the SIGHUP handler to use it (instead of
the complete teardown and reinitialization it was doing before).
---
common/gdm-settings-direct.c | 9 +++++++++
common/gdm-settings-direct.h | 2 ++
common/gdm-settings.c | 14 ++++++++++++--
common/gdm-settings.h | 1 +
daemon/main.c | 12 ++----------
5 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/common/gdm-settings-direct.c b/common/gdm-settings-direct.c
index ddb31908..5fbe0326 100644
--- a/common/gdm-settings-direct.c
+++ b/common/gdm-settings-direct.c
@@ -224,35 +224,44 @@ hashify_list (GdmSettingsEntry *entry,
gboolean
gdm_settings_direct_init (GdmSettings *settings,
const char *file,
const char *root)
{
GSList *list;
g_return_val_if_fail (file != NULL, FALSE);
g_return_val_if_fail (root != NULL, FALSE);
g_debug ("Settings Direct Init");
if (schemas != NULL) {
g_hash_table_unref (schemas);
schemas = NULL;
}
if (! gdm_settings_parse_schemas (file, root, &list)) {
g_warning ("Unable to parse schemas");
return FALSE;
}
schemas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)gdm_settings_entry_free);
g_slist_foreach (list, (GFunc)hashify_list, NULL);
settings_object = settings;
return TRUE;
}
+void
+gdm_settings_direct_reload (void)
+{
+ if (!settings_object)
+ return;
+
+ gdm_settings_reload (settings_object);
+}
+
void
gdm_settings_direct_shutdown (void)
{
}
diff --git a/common/gdm-settings-direct.h b/common/gdm-settings-direct.h
index 156489cd..6754955f 100644
--- a/common/gdm-settings-direct.h
+++ b/common/gdm-settings-direct.h
@@ -3,48 +3,50 @@
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __GDM_SETTINGS_DIRECT_H
#define __GDM_SETTINGS_DIRECT_H
#include <glib-object.h>
#include "gdm-settings.h"
G_BEGIN_DECLS
gboolean gdm_settings_direct_init (GdmSettings *settings,
const char *schemas_file,
const char *root);
+
+void gdm_settings_direct_reload (void);
void gdm_settings_direct_shutdown (void);
gboolean gdm_settings_direct_get (const char *key,
GValue *value);
gboolean gdm_settings_direct_set (const char *key,
GValue *value);
gboolean gdm_settings_direct_get_int (const char *key,
int *value);
gboolean gdm_settings_direct_get_uint (const char *key,
uint *value);
gboolean gdm_settings_direct_get_boolean (const char *key,
gboolean *value);
gboolean gdm_settings_direct_get_string (const char *key,
char **value);
G_END_DECLS
#endif /* __GDM_SETTINGS_DIRECT_H */
diff --git a/common/gdm-settings.c b/common/gdm-settings.c
index e6f46ec3..96c2f8d3 100644
--- a/common/gdm-settings.c
+++ b/common/gdm-settings.c
@@ -157,84 +157,94 @@ gdm_settings_class_init (GdmSettingsClass *klass)
object_class->finalize = gdm_settings_finalize;
signals [VALUE_CHANGED] =
g_signal_new ("value-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
3,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
}
static void
backend_value_changed (GdmSettingsBackend *backend,
const char *key,
const char *old_value,
const char *new_value,
GdmSettings *settings)
{
g_debug ("Emitting value-changed %s %s %s", key, old_value, new_value);
/* proxy it to internal listeners */
g_signal_emit (settings, signals [VALUE_CHANGED], 0, key, old_value, new_value);
}
-static void
-gdm_settings_init (GdmSettings *settings)
+void
+gdm_settings_reload (GdmSettings *settings)
{
GList *l;
GdmSettingsBackend *backend;
+ g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
+ g_list_free (settings->backends);
+ settings->backends = NULL;
+
backend = gdm_settings_desktop_backend_new (GDM_CUSTOM_CONF);
if (backend)
settings->backends = g_list_prepend (NULL, backend);
backend = gdm_settings_desktop_backend_new (GDM_RUNTIME_CONF);
if (backend)
settings->backends = g_list_prepend (settings->backends, backend);
for (l = settings->backends; l; l = g_list_next (l)) {
backend = l->data;
g_signal_connect (backend,
"value-changed",
G_CALLBACK (backend_value_changed),
settings);
}
}
+static void
+gdm_settings_init (GdmSettings *settings)
+{
+ gdm_settings_reload (settings);
+}
+
static void
gdm_settings_finalize (GObject *object)
{
GdmSettings *settings;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_SETTINGS (object));
settings = GDM_SETTINGS (object);
g_return_if_fail (settings != NULL);
g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
g_list_free (settings->backends);
settings->backends = NULL;
settings_object = NULL;
G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
}
GdmSettings *
gdm_settings_new (void)
{
if (settings_object != NULL) {
g_object_ref (settings_object);
} else {
settings_object = g_object_new (GDM_TYPE_SETTINGS, NULL);
}
diff --git a/common/gdm-settings.h b/common/gdm-settings.h
index 786868a9..07b64785 100644
--- a/common/gdm-settings.h
+++ b/common/gdm-settings.h
@@ -13,45 +13,46 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __GDM_SETTINGS_H
#define __GDM_SETTINGS_H
#include <glib-object.h>
G_BEGIN_DECLS
#define GDM_TYPE_SETTINGS (gdm_settings_get_type ())
G_DECLARE_FINAL_TYPE (GdmSettings, gdm_settings, GDM, SETTINGS, GObject)
typedef enum
{
GDM_SETTINGS_ERROR_GENERAL,
GDM_SETTINGS_ERROR_KEY_NOT_FOUND
} GdmSettingsError;
#define GDM_SETTINGS_ERROR gdm_settings_error_quark ()
GQuark gdm_settings_error_quark (void);
GdmSettings * gdm_settings_new (void);
+void gdm_settings_reload (GdmSettings *settings);
/* exported */
gboolean gdm_settings_get_value (GdmSettings *settings,
const char *key,
char **value,
GError **error);
gboolean gdm_settings_set_value (GdmSettings *settings,
const char *key,
const char *value,
GError **error);
G_END_DECLS
#endif /* __GDM_SETTINGS_H */
diff --git a/daemon/main.c b/daemon/main.c
index 1b893fe0..344d1b74 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -240,70 +240,62 @@ gdm_daemon_lookup_user (uid_t *uidp,
if G_UNLIKELY (gid == 0) {
gdm_fail (_("The GDM group should not be root. Aborting!"));
}
if (uidp != NULL) {
*uidp = uid;
}
if (gidp != NULL) {
*gidp = gid;
}
g_free (username);
g_free (groupname);
}
static gboolean
on_shutdown_signal_cb (gpointer user_data)
{
GMainLoop *mainloop = user_data;
g_main_loop_quit (mainloop);
return FALSE;
}
static gboolean
on_sighup_cb (gpointer user_data)
{
g_debug ("Got HUP signal");
- /* Reread config stuff like system config files, VPN service
- * files, etc
- */
- g_object_unref (settings);
- settings = gdm_settings_new ();
- if (settings != NULL) {
- if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
- g_warning ("Unable to initialize settings");
- }
- }
+
+ gdm_settings_reload (settings);
return TRUE;
}
static gboolean
is_debug_set (void)
{
gboolean debug;
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
return debug;
}
/* SIGUSR1 is used by the X server to tell us that we're ready, so
* block it. We'll unblock it in the worker thread in gdm-server.c
*/
static void
block_sigusr1 (void)
{
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);
sigprocmask (SIG_BLOCK, &mask, NULL);
}
int
main (int argc,
char **argv)
{
GMainLoop *main_loop;
--
2.34.1

View File

@ -0,0 +1,155 @@
From a9928bfcc9c6d81d60e047b7838d4107835b8f89 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Feb 2022 14:33:22 -0500
Subject: [PATCH 3/4] common: Reload settings when graphics initialize
If GDM starts faster than graphics initialize, then the
udev rules that write out /run/gdm/custom.conf might get
run too late for GDM to notice.
This commit changes GDM to reread its config after graphicals
initialization completes.
https://gitlab.gnome.org/GNOME/gdm/-/issues/763
---
daemon/gdm-local-display-factory.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 0b1d3482..8bca8ce9 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1023,64 +1023,66 @@ on_seat_properties_changed (GDBusConnection *connection,
g_autoptr(GVariant) changed_prop = NULL;
g_autofree const gchar **invalidated_props = NULL;
gboolean changed = FALSE;
int ret;
/* Extract seat id, i.e. the last element of the object path. */
seat = strrchr (object_path, '/');
if (seat == NULL)
return;
seat += 1;
/* Valid seat IDs must start with seat, i.e. ignore "auto" */
if (!g_str_has_prefix (seat, "seat"))
return;
g_variant_get (parameters, "(s@a{sv}^a&s)", NULL, &changed_props, &invalidated_props);
changed_prop = g_variant_lookup_value (changed_props, "CanGraphical", NULL);
if (changed_prop)
changed = TRUE;
if (!changed && g_strv_contains (invalidated_props, "CanGraphical"))
changed = TRUE;
if (!changed)
return;
ret = sd_seat_can_graphical (seat);
if (ret < 0)
return;
- if (ret != 0)
+ if (ret != 0) {
+ gdm_settings_direct_reload ();
ensure_display_for_seat (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
- else
+ } else {
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
+ }
}
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
static gboolean
lookup_by_tty (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *tty_to_find = user_data;
g_autofree char *tty_to_check = NULL;
const char *session_id;
int ret;
session_id = gdm_display_get_session_id (display);
if (!session_id)
return FALSE;
ret = sd_session_get_tty (session_id, &tty_to_check);
@@ -1260,60 +1262,61 @@ on_vt_changed (GIOChannel *source,
}
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_CONTINUE;
}
#endif
#ifdef HAVE_UDEV
static void
on_uevent (GUdevClient *client,
const char *action,
GUdevDevice *device,
GdmLocalDisplayFactory *factory)
{
if (!g_udev_device_get_device_file (device))
return;
if (g_strcmp0 (action, "add") != 0 &&
g_strcmp0 (action, "change") != 0)
return;
if (!udev_is_settled (factory))
return;
g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
factory->uevent_handler_id = 0;
+ gdm_settings_direct_reload ();
ensure_display_for_seat (factory, "seat0");
}
#endif
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
const char *subsystems[] = { "drm", NULL };
factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
factory->seat_removed_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatRemoved",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_removed,
g_object_ref (factory),
g_object_unref);
--
2.34.1

View File

@ -0,0 +1,163 @@
From 0131864b339dc0cc5f23def75e6caa5872c9ed11 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 7 Mar 2022 10:16:39 -0500
Subject: [PATCH 4/4] data: Use latest upstream udev rules
This pulls in the latest udev rule from upstream that gives us
wayland on nvidia when we can, and disables wayland on nvidia
when we should.
It also pulls in the latest handling for passthrough gpus.
---
data/61-gdm.rules.in | 139 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 135 insertions(+), 4 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index b1da191f..5dae00ea 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,6 +1,137 @@
+# identify virtio graphics cards to find passthrough setups
+SUBSYSTEM!="virtio", GOTO="gdm_virtio_device_end"
+ACTION!="add", GOTO="gdm_virtio_device_end"
+ATTR{vendor}=="0x1af4", ATTR{device}=="0x0010", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_virtio_device_end"
+LABEL="gdm_virtio_device_end"
+
+SUBSYSTEM!="pci", GOTO="gdm_pci_device_end"
+ACTION!="bind", GOTO="gdm_pci_device_end"
+
+# identify virtio graphics cards to find passthrough setups
+# cirrus
+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+# vga
+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+# qxl
+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+
# disable Wayland on Hi1710 chipsets
-ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
-# disable Wayland when using the proprietary nvidia driver
-DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", GOTO="gdm_disable_wayland"
+
+# disable Wayland on Matrox chipsets
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", GOTO="gdm_disable_wayland"
+
+# disable Wayland on aspeed chipsets
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", GOTO="gdm_disable_wayland"
+
+LABEL="gdm_pci_device_end"
+
# disable Wayland if modesetting is disabled
-IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+KERNEL!="card[0-9]*", GOTO="gdm_nomodeset_end"
+SUBSYSTEM!="drm", GOTO="gdm_nomodeset_end"
+IMPORT{parent}="GDM_MACHINE_HAS_VIRTUAL_GPU"
+ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}!="1", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hardware-gpu"
+# but keep it enabled for simple framebuffer drivers
+DRIVERS=="simple-framebuffer", GOTO="gdm_nomodeset_end"
+IMPORT{cmdline}="nomodeset", GOTO="gdm_disable_wayland"
+LABEL="gdm_nomodeset_end"
+
+# The vendor nvidia driver has multiple modules that need to be loaded before GDM can make an
+# informed choice on which way to proceed, so force GDM to wait until NVidia's modules are
+# loaded before starting up.
+KERNEL!="nvidia", GOTO="gdm_nvidia_end"
+SUBSYSTEM!="module", GOTO="gdm_nvidia_end"
+ACTION!="add", GOTO="gdm_nvidia_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-has-vendor-nvidia-driver"
+
+# Check if suspend/resume services necessary for working wayland support is available
+TEST{0711}!="/usr/bin/nvidia-sleep.sh", GOTO="gdm_disable_wayland"
+TEST{0711}!="/usr/lib/systemd/system-sleep/nvidia", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c \"sed -e 's/: /=/g' -e 's/\([^[:upper:]]\)\([[:upper:]]\)/\1_\2/g' -e 's/[[:lower:]]/\U&/g' -e 's/^/NVIDIA_/' /proc/driver/nvidia/params\""
+ENV{NVIDIA_PRESERVE_VIDEO_MEMORY_ALLOCATIONS}!="1", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_HIBERNATE=`systemctl is-enabled nvidia-hibernate`'"
+ENV{NVIDIA_HIBERNATE}!="enabled", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_RESUME=`systemctl is-enabled nvidia-resume`'"
+ENV{NVIDIA_RESUME}!="enabled", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_SUSPEND=`systemctl is-enabled nvidia-suspend`'"
+ENV{NVIDIA_SUSPEND}!="enabled", GOTO="gdm_disable_wayland"
+LABEL="gdm_nvidia_end"
+
+# If this machine has an internal panel, take note, since it's probably a laptop
+# FIXME: It could be "ghost connectors" make this pop positive for some workstations
+# in the wild. If so, we may have to fallback to looking at the chassis type from
+# dmi data or acpi
+KERNEL!="card[0-9]-eDP-*", GOTO="gdm_laptop_check_end"
+SUBSYSTEM!="drm", GOTO="gdm_laptop_check_end"
+ACTION!="add", GOTO="gdm_laptop_check_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-is-laptop"
+GOTO="gdm_hybrid_nvidia_laptop_check"
+LABEL="gdm_laptop_check_end"
+
+# If this is a hybrid graphics setup, take note
+KERNEL!="card[1-9]*", GOTO="gdm_hybrid_graphics_check_end"
+KERNEL=="card[1-9]-*", GOTO="gdm_hybrid_graphics_check_end"
+SUBSYSTEM!="drm", GOTO="gdm_hybrid_graphics_check_end"
+ACTION!="add", GOTO="gdm_hybrid_graphics_check_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hybrid-graphics"
+LABEL="gdm_hybrid_graphics_check_end"
+
+# If this is a hybrid graphics laptop with vendor nvidia driver, disable wayland
+LABEL="gdm_hybrid_nvidia_laptop_check"
+TEST!="/run/udev/gdm-machine-is-laptop", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+TEST!="/run/udev/gdm-machine-has-vendor-nvidia-driver", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+GOTO="gdm_disable_wayland"
+LABEL="gdm_hybrid_nvidia_laptop_check_end"
+
+# Disable wayland in situation where we're in a guest with a virtual gpu and host passthrough gpu
+LABEL="gdm_virt_passthrough_check"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_passthrough_check_end"
+TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_passthrough_check_end"
+TEST!="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_passthrough_check_end"
+GOTO="gdm_disable_wayland"
+LABEL="gdm_virt_passthrough_check_end"
+
+# Disable wayland when there are multiple virtual gpus
+LABEL="gdm_virt_multi_gpu_check"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_multi_gpu_check_end"
+TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_multi_gpu_check_end"
+TEST=="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_multi_gpu_check_end"
+LABEL="gdm_virt_multi_gpu_check_end"
+
+# Disable wayland when nvidia modeset is disabled or when drivers are a lower
+# version than 470,
+# For versions above 470 but lower than 510 prefer Xorg,
+# Above 510, prefer Wayland.
+KERNEL!="nvidia_drm", GOTO="gdm_nvidia_drm_end"
+SUBSYSTEM!="module", GOTO="gdm_nvidia_drm_end"
+ACTION!="add", GOTO="gdm_nvidia_drm_end"
+# disable wayland if nvidia-drm modeset is not enabled
+ATTR{parameters/modeset}!="Y", GOTO="gdm_disable_wayland"
+# disable wayland for nvidia drivers versions lower than 470
+ATTR{version}=="4[0-6][0-9].*|[0-3][0-9][0-9].*|[0-9][0-9].*|[0-9].*", GOTO="gdm_disable_wayland"
+# For nvidia drivers versions Above 510, keep Wayland by default
+ATTR{version}=="[5-9][1-9][0-9].*", GOTO="gdm_end"
+# For nvidia drivers versions 470-495, prefer Xorg by default
+GOTO="gdm_prefer_xorg"
+LABEL="gdm_nvidia_drm_end"
+
+GOTO="gdm_end"
+
+LABEL="gdm_prefer_xorg"
+RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg"
+GOTO="gdm_end"
+
+LABEL="gdm_disable_wayland"
+RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+GOTO="gdm_end"
+
+LABEL="gdm_end"
--
2.34.1

View File

@ -11,7 +11,7 @@
Name: gdm
Epoch: 1
Version: 40.1
Release: 12%{?dist}
Release: 13%{?dist}
Summary: The GNOME Display Manager
License: GPLv2+
@ -43,6 +43,12 @@ Patch60001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch
Patch60002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch
Patch60003: 0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch
# Latest udev rules and support code
Patch70001: 0001-local-display-factory-Stall-startup-until-main-graph.patch
Patch70002: 0002-common-Add-API-to-reload-settings-from-disk.patch
Patch70003: 0003-common-Reload-settings-when-graphics-initialize.patch
Patch70004: 0004-data-Use-latest-upstream-udev-rules.patch
# Non-upstreamable workarounds
Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.patch
@ -51,8 +57,6 @@ Patch99910001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch
Patch99930001: 0001-data-add-system-dconf-databases-to-gdm-profile.patch
Patch99940001: 0001-data-disable-wayland-on-certain-hardware.patch
Patch99950001: 0001-data-Disable-network-configuration-on-login-screen.patch
@ -73,6 +77,7 @@ BuildRequires: pkgconfig(accountsservice) >= 0.6.3
BuildRequires: pkgconfig(check)
BuildRequires: pkgconfig(gobject-introspection-1.0)
BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version}
BuildRequires: pkgconfig(gudev-1.0)
BuildRequires: pkgconfig(iso-codes)
BuildRequires: pkgconfig(libcanberra-gtk3)
BuildRequires: pkgconfig(libselinux)
@ -338,6 +343,11 @@ dconf update || :
%{_libdir}/pkgconfig/gdm-pam-extensions.pc
%changelog
* Mon Mar 07 2022 Ray Strode <rstrode@redhat.com> - 40.1-13
- Pull in latest udev rules and race fixes for handling
udev rules.
Related: #2060793
* Tue Feb 22 2022 Ray Strode <rstrode@redhat.com> - 40.1-12
- More fixes from RHEL 8:
- Fix DisallowTCP=false