Re: [systemd-devel] [PATCH v2 01/10] logind: listen actively for session devices
On Tue, 17.09.13 17:39, David Herrmann (dh.herrm...@gmail.com) wrote: Applied! Thanks! Session compositors need access to fbdev, DRM and evdev devices if they control a session. To make logind pass them to sessions, we need to listen for them actively. However, we avoid creating new seats for non master-of-seat devices. Only once a seat is created, we start remembering all other session devices. If the last master-device is removed (even if there are other non-master devices still available), we destroy the seat. This is the current behavior, but we need to explicitly implement it now as there may be non-master devices in the seat-devices list. Unlike master devices, we don't care whether our list of non-master devices is complete. We don't export this list but use it only as cache if sessions request these devices. Hence, if a session requests a device that is not in the list, we will simply look it up. However, once a session requested a device, we must be notified of remove udev events. So we must link the devices somehow into the device-list. Regarding the implementation, we now sort the device list by the master flag. This guarantees that master devices are at the front and non-master devices at the tail of the list. Thus, we can easily test whether a seat has a master device attached. --- src/login/logind-device.c | 35 ++--- src/login/logind-device.h | 3 +- src/login/logind-seat.c | 11 +-- src/login/logind-seat.h | 1 + src/login/logind.c| 79 +-- src/login/logind.h| 6 ++-- 6 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/login/logind-device.c b/src/login/logind-device.c index 51b1535..a9a9633 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -25,7 +25,7 @@ #include logind-device.h #include util.h -Device* device_new(Manager *m, const char *sysfs) { +Device* device_new(Manager *m, const char *sysfs, bool master) { Device *d; assert(m); @@ -48,6 +48,7 @@ Device* device_new(Manager *m, const char *sysfs) { } d-manager = m; +d-master = master; dual_timestamp_get(d-timestamp); return d; @@ -75,11 +76,16 @@ void device_detach(Device *d) { LIST_REMOVE(Device, devices, d-seat-devices, d); d-seat = NULL; -seat_add_to_gc_queue(s); -seat_send_changed(s, CanGraphical\0); +if (!seat_has_master_device(s)) { +seat_add_to_gc_queue(s); +seat_send_changed(s, CanGraphical\0); +} } void device_attach(Device *d, Seat *s) { +Device *i; +bool had_master; + assert(d); assert(s); @@ -90,7 +96,26 @@ void device_attach(Device *d, Seat *s) { device_detach(d); d-seat = s; -LIST_PREPEND(Device, devices, s-devices, d); +had_master = seat_has_master_device(s); + +/* We keep the device list sorted by the master flag. That is, master + * devices are at the front, other devices at the tail. As there is no + * way to easily add devices at the list-tail, we need to iterate the + * list to find the first non-master device when adding non-master + * devices. We assume there is only a few (normally 1) master devices + * per seat, so we iterate only a few times. */ + +if (d-master || !s-devices) { +LIST_PREPEND(Device, devices, s-devices, d); +} else { +LIST_FOREACH(devices, i, s-devices) { +if (!i-devices_next || !i-master) { +LIST_INSERT_AFTER(Device, devices, s-devices, i, d); +break; +} +} +} -seat_send_changed(s, CanGraphical\0); +if (!had_master d-master) +seat_send_changed(s, CanGraphical\0); } diff --git a/src/login/logind-device.h b/src/login/logind-device.h index 3b15356..315f0e6 100644 --- a/src/login/logind-device.h +++ b/src/login/logind-device.h @@ -33,13 +33,14 @@ struct Device { char *sysfs; Seat *seat; +bool master; dual_timestamp timestamp; LIST_FIELDS(struct Device, devices); }; -Device* device_new(Manager *m, const char *sysfs); +Device* device_new(Manager *m, const char *sysfs, bool master); void device_free(Device *d); void device_attach(Device *d, Seat *s); void device_detach(Device *d); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 470d08b..2c60b8a 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -448,10 +448,17 @@ bool seat_can_tty(Seat *s) { return seat_is_vtconsole(s); } +bool seat_has_master_device(Seat *s) { +assert(s);
[systemd-devel] [PATCH v2 01/10] logind: listen actively for session devices
Session compositors need access to fbdev, DRM and evdev devices if they control a session. To make logind pass them to sessions, we need to listen for them actively. However, we avoid creating new seats for non master-of-seat devices. Only once a seat is created, we start remembering all other session devices. If the last master-device is removed (even if there are other non-master devices still available), we destroy the seat. This is the current behavior, but we need to explicitly implement it now as there may be non-master devices in the seat-devices list. Unlike master devices, we don't care whether our list of non-master devices is complete. We don't export this list but use it only as cache if sessions request these devices. Hence, if a session requests a device that is not in the list, we will simply look it up. However, once a session requested a device, we must be notified of remove udev events. So we must link the devices somehow into the device-list. Regarding the implementation, we now sort the device list by the master flag. This guarantees that master devices are at the front and non-master devices at the tail of the list. Thus, we can easily test whether a seat has a master device attached. --- src/login/logind-device.c | 35 ++--- src/login/logind-device.h | 3 +- src/login/logind-seat.c | 11 +-- src/login/logind-seat.h | 1 + src/login/logind.c| 79 +-- src/login/logind.h| 6 ++-- 6 files changed, 116 insertions(+), 19 deletions(-) diff --git a/src/login/logind-device.c b/src/login/logind-device.c index 51b1535..a9a9633 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -25,7 +25,7 @@ #include logind-device.h #include util.h -Device* device_new(Manager *m, const char *sysfs) { +Device* device_new(Manager *m, const char *sysfs, bool master) { Device *d; assert(m); @@ -48,6 +48,7 @@ Device* device_new(Manager *m, const char *sysfs) { } d-manager = m; +d-master = master; dual_timestamp_get(d-timestamp); return d; @@ -75,11 +76,16 @@ void device_detach(Device *d) { LIST_REMOVE(Device, devices, d-seat-devices, d); d-seat = NULL; -seat_add_to_gc_queue(s); -seat_send_changed(s, CanGraphical\0); +if (!seat_has_master_device(s)) { +seat_add_to_gc_queue(s); +seat_send_changed(s, CanGraphical\0); +} } void device_attach(Device *d, Seat *s) { +Device *i; +bool had_master; + assert(d); assert(s); @@ -90,7 +96,26 @@ void device_attach(Device *d, Seat *s) { device_detach(d); d-seat = s; -LIST_PREPEND(Device, devices, s-devices, d); +had_master = seat_has_master_device(s); + +/* We keep the device list sorted by the master flag. That is, master + * devices are at the front, other devices at the tail. As there is no + * way to easily add devices at the list-tail, we need to iterate the + * list to find the first non-master device when adding non-master + * devices. We assume there is only a few (normally 1) master devices + * per seat, so we iterate only a few times. */ + +if (d-master || !s-devices) { +LIST_PREPEND(Device, devices, s-devices, d); +} else { +LIST_FOREACH(devices, i, s-devices) { +if (!i-devices_next || !i-master) { +LIST_INSERT_AFTER(Device, devices, s-devices, i, d); +break; +} +} +} -seat_send_changed(s, CanGraphical\0); +if (!had_master d-master) +seat_send_changed(s, CanGraphical\0); } diff --git a/src/login/logind-device.h b/src/login/logind-device.h index 3b15356..315f0e6 100644 --- a/src/login/logind-device.h +++ b/src/login/logind-device.h @@ -33,13 +33,14 @@ struct Device { char *sysfs; Seat *seat; +bool master; dual_timestamp timestamp; LIST_FIELDS(struct Device, devices); }; -Device* device_new(Manager *m, const char *sysfs); +Device* device_new(Manager *m, const char *sysfs, bool master); void device_free(Device *d); void device_attach(Device *d, Seat *s); void device_detach(Device *d); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 470d08b..2c60b8a 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -448,10 +448,17 @@ bool seat_can_tty(Seat *s) { return seat_is_vtconsole(s); } +bool seat_has_master_device(Seat *s) { +assert(s); + +/* device list is ordered by master flag */ +return !!s-devices s-devices-master; +} + bool seat_can_graphical(Seat *s) { assert(s); -return !!s-devices; +return