Re: [systemd-devel] [PATCH v2 01/10] logind: listen actively for session devices

2013-09-17 Thread Lennart Poettering
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

2013-09-17 Thread David Herrmann
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