summaryrefslogtreecommitdiff
path: root/src/login/logind-session-device.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-03-06 20:13:05 +0100
committerMichael Biebl <biebl@debian.org>2018-03-06 20:13:05 +0100
commit98393f852f2f66a74f7370aa63c07b26d610343c (patch)
tree627d6c5463c0e6ac9f4f6243a9c9274acdae197d /src/login/logind-session-device.c
parent1d42b86df9052528a8f56b2f52d8bc2faf87b2da (diff)
downloadsystemd-98393f852f2f66a74f7370aa63c07b26d610343c.tar.gz
New upstream version 238
Diffstat (limited to 'src/login/logind-session-device.c')
-rw-r--r--src/login/logind-session-device.c135
1 files changed, 73 insertions, 62 deletions
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index 067e67a93d..73eee72515 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -74,20 +74,25 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return r;
switch (type) {
+
case SESSION_DEVICE_RESUME:
r = sd_bus_message_append(m, "uuh", major, minor, sd->fd);
if (r < 0)
return r;
break;
+
case SESSION_DEVICE_TRY_PAUSE:
t = "pause";
break;
+
case SESSION_DEVICE_PAUSE:
t = "force";
break;
+
case SESSION_DEVICE_RELEASE:
t = "gone";
break;
+
default:
return -EINVAL;
}
@@ -101,43 +106,33 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati
return sd_bus_send(sd->session->manager->bus, m, NULL);
}
-static int sd_eviocrevoke(int fd) {
- static bool warned;
- int r;
+static void sd_eviocrevoke(int fd) {
+ static bool warned = false;
assert(fd >= 0);
- r = ioctl(fd, EVIOCREVOKE, NULL);
- if (r < 0) {
- r = -errno;
- if (r == -EINVAL && !warned) {
+ if (ioctl(fd, EVIOCREVOKE, NULL) < 0) {
+
+ if (errno == EINVAL && !warned) {
+ log_warning_errno(errno, "Kernel does not support evdev-revocation: %m");
warned = true;
- log_warning("kernel does not support evdev-revocation");
}
}
-
- return 0;
}
static int sd_drmsetmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0)
return -errno;
return 0;
}
static int sd_drmdropmaster(int fd) {
- int r;
-
assert(fd >= 0);
- r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
- if (r < 0)
+ if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0)
return -errno;
return 0;
@@ -146,7 +141,9 @@ static int sd_drmdropmaster(int fd) {
static int session_device_open(SessionDevice *sd, bool active) {
int fd, r;
+ assert(sd);
assert(sd->type != DEVICE_TYPE_UNKNOWN);
+ assert(sd->node);
/* open device and try to get an udev_device from it */
fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
@@ -154,28 +151,27 @@ static int session_device_open(SessionDevice *sd, bool active) {
return -errno;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
if (active) {
- /* Weird legacy DRM semantics might return an error
- * even though we're master. No way to detect that so
- * fail at all times and let caller retry in inactive
- * state. */
+ /* Weird legacy DRM semantics might return an error even though we're master. No way to detect
+ * that so fail at all times and let caller retry in inactive state. */
r = sd_drmsetmaster(fd);
if (r < 0) {
close_nointr(fd);
return r;
}
- } else {
- /* DRM-Master is granted to the first user who opens a
- * device automatically (ughh, racy!). Hence, we just
- * drop DRM-Master in case we were the first. */
- sd_drmdropmaster(fd);
- }
+ } else
+ /* DRM-Master is granted to the first user who opens a device automatically (ughh,
+ * racy!). Hence, we just drop DRM-Master in case we were the first. */
+ (void) sd_drmdropmaster(fd);
break;
+
case DEVICE_TYPE_EVDEV:
if (!active)
sd_eviocrevoke(fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices wihout synchronizations */
@@ -195,29 +191,38 @@ static int session_device_start(SessionDevice *sd) {
return 0;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
- /* Device is kept open. Simply call drmSetMaster() and hope
- * there is no-one else. In case it fails, we keep the device
- * paused. Maybe at some point we have a drmStealMaster(). */
- r = sd_drmsetmaster(sd->fd);
- if (r < 0)
- return r;
+
+ if (sd->fd < 0) {
+ /* Open device if it isn't open yet */
+ sd->fd = session_device_open(sd, true);
+ if (sd->fd < 0)
+ return sd->fd;
+ } else {
+ /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we
+ * keep the device paused. Maybe at some point we have a drmStealMaster(). */
+ r = sd_drmsetmaster(sd->fd);
+ if (r < 0)
+ return r;
+ }
break;
+
case DEVICE_TYPE_EVDEV:
- /* Evdev devices are revoked while inactive. Reopen it and we
- * are fine. */
+ /* Evdev devices are revoked while inactive. Reopen it and we are fine. */
r = session_device_open(sd, true);
if (r < 0)
return r;
- /* For evdev devices, the file descriptor might be left
- * uninitialized. This might happen while resuming into a
- * session and logind has been restarted right before. */
+
+ /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming
+ * into a session and logind has been restarted right before. */
safe_close(sd->fd);
sd->fd = r;
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
- /* fallback for devices wihout synchronizations */
+ /* fallback for devices without synchronizations */
break;
}
@@ -232,6 +237,7 @@ static void session_device_stop(SessionDevice *sd) {
return;
switch (sd->type) {
+
case DEVICE_TYPE_DRM:
/* On DRM devices we simply drop DRM-Master but keep it open.
* This allows the user to keep resources allocated. The
@@ -239,6 +245,7 @@ static void session_device_stop(SessionDevice *sd) {
* circumventing this. */
sd_drmdropmaster(sd->fd);
break;
+
case DEVICE_TYPE_EVDEV:
/* Revoke access on evdev file-descriptors during deactivation.
* This will basically prevent any operations on the fd and
@@ -246,6 +253,7 @@ static void session_device_stop(SessionDevice *sd) {
* protection this way. */
sd_eviocrevoke(sd->fd);
break;
+
case DEVICE_TYPE_UNKNOWN:
default:
/* fallback for devices without synchronization */
@@ -371,10 +379,8 @@ int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **
goto error;
r = hashmap_put(s->devices, &sd->dev, sd);
- if (r < 0) {
- r = -ENOMEM;
+ if (r < 0)
goto error;
- }
if (open_device) {
/* Open the device for the first time. We need a valid fd to pass back
@@ -423,7 +429,7 @@ void session_device_free(SessionDevice *sd) {
session_device_stop(sd);
session_device_notify(sd, SESSION_DEVICE_RELEASE);
- close_nointr(sd->fd);
+ safe_close(sd->fd);
LIST_REMOVE(sd_by_device, sd->device->session_devices, sd);
@@ -458,13 +464,15 @@ void session_device_resume_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (!sd->active) {
- if (session_device_start(sd) < 0)
- continue;
- if (session_device_save(sd) < 0)
- continue;
- session_device_notify(sd, SESSION_DEVICE_RESUME);
- }
+ if (sd->active)
+ continue;
+
+ if (session_device_start(sd) < 0)
+ continue;
+ if (session_device_save(sd) < 0)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_RESUME);
}
}
@@ -475,25 +483,27 @@ void session_device_pause_all(Session *s) {
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_stop(sd);
- session_device_notify(sd, SESSION_DEVICE_PAUSE);
- }
+ if (!sd->active)
+ continue;
+
+ session_device_stop(sd);
+ session_device_notify(sd, SESSION_DEVICE_PAUSE);
}
}
unsigned int session_device_try_pause_all(Session *s) {
+ unsigned num_pending = 0;
SessionDevice *sd;
Iterator i;
- unsigned int num_pending = 0;
assert(s);
HASHMAP_FOREACH(sd, s->devices, i) {
- if (sd->active) {
- session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
- ++num_pending;
- }
+ if (!sd->active)
+ continue;
+
+ session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE);
+ num_pending++;
}
return num_pending;
@@ -516,7 +526,7 @@ int session_device_save(SessionDevice *sd) {
return 0;
m = strjoina("FDSTORE=1\n"
- "FDNAME=session", sd->session->id);
+ "FDNAME=session-", sd->session->id);
r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1);
if (r < 0)
@@ -527,11 +537,12 @@ int session_device_save(SessionDevice *sd) {
}
void session_device_attach_fd(SessionDevice *sd, int fd, bool active) {
- assert(fd > 0);
+ assert(fd >= 0);
assert(sd);
assert(sd->fd < 0);
assert(!sd->active);
sd->fd = fd;
+ sd->pushed_fd = true;
sd->active = active;
}