diff options
author | Michael Biebl <biebl@debian.org> | 2018-03-06 20:13:05 +0100 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2018-03-06 20:13:05 +0100 |
commit | 98393f852f2f66a74f7370aa63c07b26d610343c (patch) | |
tree | 627d6c5463c0e6ac9f4f6243a9c9274acdae197d /src/login/logind-session-device.c | |
parent | 1d42b86df9052528a8f56b2f52d8bc2faf87b2da (diff) | |
download | systemd-98393f852f2f66a74f7370aa63c07b26d610343c.tar.gz |
New upstream version 238
Diffstat (limited to 'src/login/logind-session-device.c')
-rw-r--r-- | src/login/logind-session-device.c | 135 |
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; } |