[PATCH v2 11/14] systemd-logind: Hookup systemd-logind integration

Hans de Goede hdegoede at redhat.com
Tue Feb 4 12:49:17 CET 2014


This commits makes the changes necessary outside of the systemd-logind core
to make the server use systemd-logind managed fds for input devices and drm
nodes.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 config/config.c                            | 13 ++++++++++
 config/udev.c                              | 39 +++++++++++++++++++++++++++---
 hw/xfree86/common/xf86Events.c             | 15 +++++++++---
 hw/xfree86/common/xf86Xinput.c             | 18 ++++++++++++++
 hw/xfree86/os-support/linux/lnx_platform.c | 32 +++++++++++++++++++++---
 5 files changed, 107 insertions(+), 10 deletions(-)

diff --git a/config/config.c b/config/config.c
index 5833992..ebfe6a1 100644
--- a/config/config.c
+++ b/config/config.c
@@ -27,10 +27,12 @@
 #include <dix-config.h>
 #endif
 
+#include <unistd.h>
 #include "os.h"
 #include "inputstr.h"
 #include "hotplug.h"
 #include "config-backends.h"
+#include "systemd-logind.h"
 
 void
 config_pre_init(void)
@@ -231,10 +233,21 @@ void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
     struct OdevAttribute *iter, *safe;
+    int major = 0, minor = 0, fd = -1;
 
     xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
+        switch (iter->attrib_id) {
+        case ODEV_ATTRIB_MAJOR: major = iter->attrib_value; break;
+        case ODEV_ATTRIB_MINOR: minor = iter->attrib_value; break;
+        case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
+        }
         xorg_list_del(&iter->member);
         free(iter->attrib_name);
         free(iter);
     }
+
+    if (fd != -1) {
+        systemd_logind_release_fd(major, minor);
+        close(fd);
+    }
 }
diff --git a/config/udev.c b/config/udev.c
index 436b8f0..e888ab1 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -29,6 +29,7 @@
 
 #include <libudev.h>
 #include <ctype.h>
+#include <unistd.h>
 
 #include "input.h"
 #include "inputstr.h"
@@ -36,6 +37,7 @@
 #include "config-backends.h"
 #include "os.h"
 #include "globals.h"
+#include "systemd-logind.h"
 
 #define UDEV_XKB_PROP_KEY "xkb"
 
@@ -55,9 +57,18 @@ static struct udev_monitor *udev_monitor;
 #ifdef CONFIG_UDEV_KMS
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback);
 #endif
 
+static char itoa_buf[16];
+
+static const char *itoa(int i)
+{
+    snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
+    return itoa_buf;
+}
+
 static void
 device_added(struct udev_device *udev_device)
 {
@@ -73,6 +84,7 @@ device_added(struct udev_device *udev_device)
     struct udev_device *parent;
     int rc;
     const char *dev_seat;
+    dev_t devnum;
 
     path = udev_device_get_devnode(udev_device);
 
@@ -91,6 +103,8 @@ device_added(struct udev_device *udev_device)
     if (!SeatId && strcmp(dev_seat, "seat0"))
         return;
 
+    devnum = udev_device_get_devnum(udev_device);
+
 #ifdef CONFIG_UDEV_KMS
     if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
         const char *sysname = udev_device_get_sysname(udev_device);
@@ -100,7 +114,8 @@ device_added(struct udev_device *udev_device)
 
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
-        config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), NewGPUDeviceRequest);
         return;
     }
 #endif
@@ -153,6 +168,8 @@ device_added(struct udev_device *udev_device)
     input_options = input_option_new(input_options, "name", name);
     input_options = input_option_new(input_options, "path", path);
     input_options = input_option_new(input_options, "device", path);
+    input_options = input_option_new(input_options, "major", itoa(major(devnum)));
+    input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
     if (path)
         attrs.device = strdup(path);
 
@@ -270,6 +287,7 @@ device_removed(struct udev_device *device)
     if (!strcmp(udev_device_get_subsystem(device), "drm")) {
         const char *sysname = udev_device_get_sysname(device);
         const char *path = udev_device_get_devnode(device);
+        dev_t devnum = udev_device_get_devnum(device);
 
         if (strncmp(sysname,"card", 4) != 0)
             return;
@@ -277,7 +295,10 @@ device_removed(struct udev_device *device)
         if (!path)
             return;
 
-        config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), DeleteGPUDeviceRequest);
+        /* Retry vtenter after a drm node removal */
+        systemd_logind_vtenter();
         return;
     }
 #endif
@@ -427,6 +448,7 @@ config_udev_fini(void)
 
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback)
 {
     struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
@@ -443,6 +465,14 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
     if (ret == FALSE)
         goto fail;
 
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
+    if (ret == FALSE)
+        goto fail;
+
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
+    if (ret == FALSE)
+        goto fail;
+
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
     return TRUE;
@@ -477,6 +507,7 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
         const char *path = udev_device_get_devnode(udev_device);
         const char *sysname = udev_device_get_sysname(udev_device);
+        dev_t devnum = udev_device_get_devnum(udev_device);
 
         if (!path || !syspath)
             goto no_probe;
@@ -485,8 +516,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         else if (strncmp(sysname, "card", 4) != 0)
             goto no_probe;
 
-        config_udev_odev_setup_attribs(path, syspath, probe_callback);
-
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), probe_callback);
     no_probe:
         udev_device_unref(udev_device);
     }
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 7b53949..06af739 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -85,6 +85,8 @@
 #endif
 
 #include "xf86platformBus.h"
+#include "systemd-logind.h"
+
 /*
  * This is a toggling variable:
  *  FALSE = No VT switching keys have been pressed last time around
@@ -556,8 +558,11 @@ xf86VTEnter(void)
     /* Turn screen saver off when switching back */
     dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
 
-    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
-        xf86EnableInputDeviceForVTSwitch(pInfo);
+    /* If we use systemd-logind it will enable input devices for us */
+    if (!systemd_logind_controls_session())
+        for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+
     for (ih = InputHandlers; ih; ih = ih->next) {
         if (ih->is_input)
             xf86EnableInputHandler(ih);
@@ -589,10 +594,14 @@ xf86VTSwitch(void)
     /*
      * Since all screens are currently all in the same state it is sufficient
      * check the first.  This might change in future.
+     *
+     * VTLeave is always handled here (VT_PROCESS guarantees this is safe),
+     * if we use systemd_logind xf86VTEnter() gets called by systemd-logind.c
+     * once it has resumed all drm nodes.
      */
     if (xf86VTOwner())
         xf86VTLeave();
-    else
+    else if (!systemd_logind_controls_session())
         xf86VTEnter();
 }
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6404ef5..9ad07ca 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -63,6 +63,7 @@
 #include "mipointer.h"
 #include "extinit.h"
 #include "loaderProcs.h"
+#include "systemd-logind.h"
 
 #include "exevents.h"           /* AddInputDevice */
 #include "exglobals.h"
@@ -80,6 +81,7 @@
 
 #include <stdarg.h>
 #include <stdint.h>             /* for int64_t */
+#include <unistd.h>
 
 #include "mi.h"
 
@@ -773,6 +775,11 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
         /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
     }
 
+    if (pInp->flags & XI86_SERVER_FD) {
+        systemd_logind_release_fd(pInp->major, pInp->minor);
+        close(pInp->fd);
+    }
+
     free((void *) pInp->driver);
     free((void *) pInp->name);
     xf86optionListFree(pInp->options);
@@ -816,6 +823,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
 {
     InputDriverPtr drv = NULL;
     DeviceIntPtr dev = NULL;
+    Bool paused;
     int rval;
 
     /* Memory leak for every attached device if we don't
@@ -830,6 +838,16 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
         goto unwind;
     }
 
+    if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
+        pInfo->fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+                                           pInfo->attrs->device, &paused);
+        if (pInfo->fd != -1) {
+            /* FIXME handle paused */
+            pInfo->flags |= XI86_SERVER_FD;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+        }
+    }
+
     xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName,
             pInfo->name);
 
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index f4c4d12..109a9a7 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -18,16 +18,38 @@
 #include "xf86Bus.h"
 
 #include "hotplug.h"
+#include "systemd-logind.h"
 
 static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 {
     drmSetVersion sv;
     char *buf;
-    int fd;
+    int major, minor, fd;
     int err = 0;
+    Bool paused, server_fd = FALSE;
+
+    major = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MAJOR, 0);
+    minor = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MINOR, 0);
+
+    fd = systemd_logind_take_fd(major, minor, path, &paused);
+    if (fd != -1) {
+        if (paused) {
+            LogMessage(X_ERROR,
+                    "Error systemd-logind returned paused fd for drm node\n");
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        if (!config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd)) {
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        server_fd = TRUE;
+    }
+
+    if (fd == -1)
+        fd = open(path, O_RDWR, O_CLOEXEC);
 
-    fd = open(path, O_RDWR, O_CLOEXEC);
     if (fd == -1)
         return FALSE;
 
@@ -48,12 +70,16 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
             delayed_index = xf86_num_platform_devices - 1;
     }
 
+    if (server_fd)
+        xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD;
+
     buf = drmGetBusid(fd);
     xf86_add_platform_device_attrib(delayed_index,
                                     ODEV_ATTRIB_BUSID, buf);
     drmFreeBusid(buf);
 out:
-    close(fd);
+    if (!server_fd)
+        close(fd);
     return (err == 0);
 }
 
-- 
1.8.5.3



More information about the xorg-devel mailing list