Blame SOURCES/0001-ply-device-manager-Fix-race-causing-undesired-creati.patch

c70ebb
From f76757f9dd63407686b24c98e5c2290502bcbb93 Mon Sep 17 00:00:00 2001
c70ebb
From: Hans de Goede <hdegoede@redhat.com>
c70ebb
Date: Tue, 26 Mar 2019 15:10:28 -0400
c70ebb
Subject: [PATCH] ply-device-manager: Fix race causing undesired creation of
c70ebb
 non-gfx devs
c70ebb
c70ebb
On systems with working drm/kms devices we still sometimes see:
c70ebb
"Creating non-graphical devices, since there's no suitable graphics hardware"
c70ebb
in the logs (and actually create non-gfx devices).
c70ebb
c70ebb
This is caused by a race where the create_devices_from_udev timeout handler
c70ebb
runs just after the pivot-root, just at the time when the "udev trigger"
c70ebb
from the real root is done.
c70ebb
c70ebb
This causes create_devices_for_subsystem() to hit the "it's not initialized"
c70ebb
code-path for all drm and fb devices, even though before (from the initrd)
c70ebb
drm-devices where already setup successfully.
c70ebb
c70ebb
One way of solving this would be to stop the timer as soon as we successfully
c70ebb
enumerate the first drm device. But we need the timer to enumerate fb devices
c70ebb
so on machines where some outputs only have a fbdev driver (corner case) this
c70ebb
would break support for those outputs.
c70ebb
c70ebb
Instead this commit moves the found_drm_device and found_fb_device to the
c70ebb
global manager state and sets them from create_devices_for_udev_device().
c70ebb
This way they will be set when we check them from the create_devices_from_udev
c70ebb
timeout handler even if create_devices_for_subsystem skips over the devices
c70ebb
because of the udev trigger race.
c70ebb
c70ebb
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
c70ebb
---
c70ebb
 src/libply-splash-core/ply-device-manager.c |  19 +-
c70ebb
 1 files changed, 63 insertions(+), 60 deletions(-)
c70ebb
c70ebb
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
c70ebb
index 3a2db06..b6437c5 100644
c70ebb
--- a/src/libply-splash-core/ply-device-manager.c
c70ebb
+++ b/src/libply-splash-core/ply-device-manager.c
c70ebb
@@ -47,60 +47,63 @@ static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t
c70ebb
                                                            ply_renderer_type_t   renderer_type);
c70ebb
 struct _ply_device_manager
c70ebb
 {
c70ebb
   ply_device_manager_flags_t  flags;
c70ebb
   ply_event_loop_t           *loop;
c70ebb
   ply_hashtable_t            *terminals;
c70ebb
   ply_hashtable_t            *renderers;
c70ebb
   ply_terminal_t             *local_console_terminal;
c70ebb
   ply_list_t                 *keyboards;
c70ebb
   ply_list_t                 *text_displays;
c70ebb
   ply_list_t                 *pixel_displays;
c70ebb
   struct udev                *udev_context;
c70ebb
   struct udev_queue          *udev_queue;
c70ebb
   int                         udev_queue_fd;
c70ebb
   ply_fd_watch_t             *udev_queue_fd_watch;
c70ebb
   struct udev_monitor        *udev_monitor;
c70ebb
 
c70ebb
   ply_keyboard_added_handler_t         keyboard_added_handler;
c70ebb
   ply_keyboard_removed_handler_t       keyboard_removed_handler;
c70ebb
   ply_pixel_display_added_handler_t    pixel_display_added_handler;
c70ebb
   ply_pixel_display_removed_handler_t  pixel_display_removed_handler;
c70ebb
   ply_text_display_added_handler_t     text_display_added_handler;
c70ebb
   ply_text_display_removed_handler_t   text_display_removed_handler;
c70ebb
   void                                *event_handler_data;
c70ebb
 
c70ebb
   uint32_t                    local_console_managed : 1;
c70ebb
   uint32_t                    local_console_is_text : 1;
c70ebb
   uint32_t                    serial_consoles_detected : 1;
c70ebb
   uint32_t                    renderers_activated : 1;
c70ebb
   uint32_t                    keyboards_activated : 1;
c70ebb
+
c70ebb
+  uint32_t                    found_drm_device : 1;
c70ebb
+  uint32_t                    found_fb_device : 1;
c70ebb
 };
c70ebb
 
c70ebb
 static void
c70ebb
 detach_from_event_loop (ply_device_manager_t *manager)
c70ebb
 {
c70ebb
   assert (manager != NULL);
c70ebb
 
c70ebb
   manager->loop = NULL;
c70ebb
 }
c70ebb
 
c70ebb
 static void
c70ebb
 attach_to_event_loop (ply_device_manager_t *manager,
c70ebb
                       ply_event_loop_t     *loop)
c70ebb
 {
c70ebb
   assert (manager != NULL);
c70ebb
   assert (loop != NULL);
c70ebb
   assert (manager->loop == NULL);
c70ebb
 
c70ebb
   manager->loop = loop;
c70ebb
 
c70ebb
   ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
c70ebb
                                  detach_from_event_loop,
c70ebb
                                  manager);
c70ebb
 }
c70ebb
 
c70ebb
 static bool
c70ebb
 drm_device_in_use (ply_device_manager_t *manager,
c70ebb
                    const char           *device_path)
c70ebb
 {
c70ebb
   ply_renderer_t *renderer;
c70ebb
@@ -183,60 +186,68 @@ create_devices_for_udev_device (ply_device_manager_t *manager,
c70ebb
         {
c70ebb
           ply_trace ("found DRM device %s", device_path);
c70ebb
           renderer_type = PLY_RENDERER_TYPE_DRM;
c70ebb
         }
c70ebb
       else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0)
c70ebb
         {
c70ebb
           ply_trace ("found frame buffer device %s", device_path);
c70ebb
           if (!fb_device_has_drm_device (manager, device))
c70ebb
             {
c70ebb
               renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER;
c70ebb
             }
c70ebb
           else
c70ebb
             {
c70ebb
               ply_trace ("ignoring, since there's a DRM device associated with it");
c70ebb
             }
c70ebb
         }
c70ebb
 
c70ebb
       if (renderer_type != PLY_RENDERER_TYPE_NONE)
c70ebb
         {
c70ebb
           ply_terminal_t *terminal = NULL;
c70ebb
 
c70ebb
           if (!manager->local_console_managed)
c70ebb
             {
c70ebb
               terminal = manager->local_console_terminal;
c70ebb
             }
c70ebb
 
c70ebb
           created = create_devices_for_terminal_and_renderer_type (manager,
c70ebb
                                                                    device_path,
c70ebb
                                                                    terminal,
c70ebb
                                                                    renderer_type);
c70ebb
+
c70ebb
+          if (created)
c70ebb
+            {
c70ebb
+              if (renderer_type == PLY_RENDERER_TYPE_DRM)
c70ebb
+                manager->found_drm_device = 1;
c70ebb
+              if (renderer_type == PLY_RENDERER_TYPE_FRAME_BUFFER)
c70ebb
+                manager->found_fb_device = 1;
c70ebb
+            }
c70ebb
        }
c70ebb
     }
c70ebb
     return created;
c70ebb
 }
c70ebb
 
c70ebb
 static void
c70ebb
 free_displays_for_renderer (ply_device_manager_t *manager,
c70ebb
                             ply_renderer_t       *renderer)
c70ebb
 {
c70ebb
   ply_list_node_t *node;
c70ebb
 
c70ebb
   node = ply_list_get_first_node (manager->pixel_displays);
c70ebb
   while (node != NULL)
c70ebb
     {
c70ebb
       ply_list_node_t *next_node;
c70ebb
       ply_pixel_display_t *display;
c70ebb
       ply_renderer_t *display_renderer;
c70ebb
 
c70ebb
       display = ply_list_node_get_data (node);
c70ebb
       next_node = ply_list_get_next_node (manager->pixel_displays, node);
c70ebb
       display_renderer = ply_pixel_display_get_renderer (display);
c70ebb
 
c70ebb
       if (display_renderer == renderer)
c70ebb
         {
c70ebb
           if (manager->pixel_display_removed_handler != NULL)
c70ebb
             manager->pixel_display_removed_handler (manager->event_handler_data, display);
c70ebb
 
c70ebb
           ply_pixel_display_free (display);
c70ebb
           ply_list_remove_node (manager->pixel_displays, node);
c70ebb
         }
c70ebb
@@ -782,68 +793,66 @@ create_devices_from_terminals (ply_device_manager_t *manager)
c70ebb
   ply_trace ("checking for consoles");
c70ebb
 
c70ebb
   if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES)
c70ebb
     {
c70ebb
       has_serial_consoles = false;
c70ebb
       ply_trace ("ignoring all consoles but default console because explicitly told to.");
c70ebb
     }
c70ebb
   else
c70ebb
     {
c70ebb
       has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active");
c70ebb
     }
c70ebb
 
c70ebb
   if (has_serial_consoles)
c70ebb
     {
c70ebb
       ply_trace ("serial consoles detected, managing them with details forced");
c70ebb
       manager->serial_consoles_detected = true;
c70ebb
 
c70ebb
       ply_hashtable_foreach (manager->terminals,
c70ebb
                              (ply_hashtable_foreach_func_t *)
c70ebb
                              create_devices_for_terminal,
c70ebb
                              manager);
c70ebb
       return true;
c70ebb
     }
c70ebb
 
c70ebb
   return false;
c70ebb
 }
c70ebb
 
c70ebb
 static void
c70ebb
 create_devices_from_udev (ply_device_manager_t *manager)
c70ebb
 {
c70ebb
-  bool found_drm_device, found_fb_device;
c70ebb
-
c70ebb
   ply_trace ("Looking for devices from udev");
c70ebb
 
c70ebb
-  found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
c70ebb
-  found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
c70ebb
+  create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
c70ebb
+  create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
c70ebb
 
c70ebb
-  if (found_drm_device || found_fb_device)
c70ebb
+  if (manager->found_drm_device || manager->found_fb_device)
c70ebb
     return;
c70ebb
 
c70ebb
   ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware");
c70ebb
   create_devices_for_terminal_and_renderer_type (manager,
c70ebb
                                                  ply_terminal_get_name (manager->local_console_terminal),
c70ebb
                                                  manager->local_console_terminal,
c70ebb
                                                  PLY_RENDERER_TYPE_NONE);
c70ebb
 }
c70ebb
 
c70ebb
 static void
c70ebb
 create_fallback_devices (ply_device_manager_t *manager)
c70ebb
 {
c70ebb
   create_devices_for_terminal_and_renderer_type (manager,
c70ebb
                                                  ply_terminal_get_name (manager->local_console_terminal),
c70ebb
                                                  manager->local_console_terminal,
c70ebb
                                                  PLY_RENDERER_TYPE_AUTO);
c70ebb
 }
c70ebb
 
c70ebb
 static void
c70ebb
 on_udev_queue_changed (ply_device_manager_t *manager)
c70ebb
 {
c70ebb
 
c70ebb
   if (!udev_queue_get_queue_is_empty (manager->udev_queue))
c70ebb
     return;
c70ebb
 
c70ebb
   ply_trace ("udev coldplug complete");
c70ebb
   ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch);
c70ebb
   manager->udev_queue_fd_watch = NULL;
c70ebb
   udev_queue_unref (manager->udev_queue);
c70ebb
 
c70ebb
-- 
c70ebb
2.20.1
c70ebb