From 99024d17b1d5672668fda412148b87d8cf33cedf Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 1 Apr 2011 19:06:59 +0200 Subject: [PATCH 1/4] Use in-kernel media probing when available Check whether the kernel supports in-kernel media polling (since 2.6.38, https://lkml.org/lkml/2010/12/8/299), and use it instead of user-space polling. Preparation for bug #34710. --- src/device-private.c | 22 +++++++++++++++++ src/device-private.h | 6 +++++ src/poller.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 0 deletions(-) diff --git a/src/device-private.c b/src/device-private.c index 22a0d35..d4ec6c5 100644 --- a/src/device-private.c +++ b/src/device-private.c @@ -187,6 +187,28 @@ device_set_job_percentage (Device *device, } void +device_set_supports_media_change_event (Device *device, + gboolean value) +{ + if (G_UNLIKELY (device->priv->supports_media_change_event != value)) + { + device->priv->supports_media_change_event = value; + emit_changed (device, "supports_media_change_event"); + } +} + +void +device_set_supports_eject_request_event (Device *device, + gboolean value) +{ + if (G_UNLIKELY (device->priv->supports_eject_request_event != value)) + { + device->priv->supports_eject_request_event = value; + emit_changed (device, "supports_eject_request_event"); + } +} + +void device_set_device_file (Device *device, const gchar *value) { diff --git a/src/device-private.h b/src/device-private.h index a6db7f2..01149e5 100644 --- a/src/device-private.h +++ b/src/device-private.h @@ -59,6 +59,9 @@ struct DevicePrivate gboolean job_is_cancellable; double job_percentage; + gboolean supports_media_change_event; + gboolean supports_eject_request_event; + guint linux_md_poll_timeout_id; /* A list of current polling inhibitors (Inhibitor objects) */ @@ -250,6 +253,9 @@ void device_set_job_initiated_by_uid (Device *device, guint value); void device_set_job_is_cancellable (Device *device, gboolean value); void device_set_job_percentage (Device *device, gdouble value); +void device_set_supports_media_change_event (Device *device, gboolean value); +void device_set_supports_eject_request_event (Device *device, gboolean value); + void device_set_device_detection_time (Device *device, guint64 value); void device_set_device_media_detection_time (Device *device, guint64 value); void device_set_device_file (Device *device, const gchar *value); diff --git a/src/poller.c b/src/poller.c index 9517b5d..1bf265b 100644 --- a/src/poller.c +++ b/src/poller.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "poller.h" #include "device.h" @@ -304,6 +305,64 @@ poller_setup (int argc, /* ---------------------------------------------------------------------------------------------------- */ +static gboolean +check_in_kernel_polling (Device* d) +{ + const char *supported_events; + gboolean ret = FALSE; + + /* only check once */ + if (d->priv->supports_media_change_event) + return TRUE; + + supported_events = g_udev_device_get_sysfs_attr (d->priv->d, "events"); + +#ifdef POLL_SHOW_DEBUG + g_print("**** POLLER (%d): Supported events for %s: %s\n", getpid (), d->priv->device_file, supported_events); +#endif + + if (strstr (supported_events, "eject_request")) + device_set_supports_eject_request_event (d, TRUE); + + if (strstr (supported_events, "media_change")) + { + /* enable in-kernel polling */ + if (g_udev_device_get_sysfs_attr_as_int (d->priv->d, "events_poll_msecs") <= 0) + { + int fd; + char *attr = g_build_filename (d->priv->native_path, "events_poll_msecs", NULL); + const char* poll_time = "2000"; + size_t poll_time_size = strlen (poll_time); + + fd = open (attr, O_WRONLY); + g_free (attr); + if (fd > 0) + { + if (write (fd, poll_time, poll_time_size) == (ssize_t) poll_time_size) + { +#ifdef POLL_SHOW_DEBUG + g_print("**** POLLER (%d): Successfully enabled in-kernel polling for %s\n", getpid (), d->priv->device_file); +#endif + device_set_supports_media_change_event (d, TRUE); + ret = TRUE; + } + close (fd); + } + } else { + /* there is already a poll time set */ +#ifdef POLL_SHOW_DEBUG + g_print("**** POLLER (%d): In-kernel polling for %s already enabled\n", getpid (), d->priv->device_file); +#endif + device_set_supports_media_change_event (d, TRUE); + ret = TRUE; + } + } + + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + void poller_set_devices (GList *devices) { @@ -320,6 +379,9 @@ poller_set_devices (GList *devices) { Device *device = DEVICE (l->data); + if (check_in_kernel_polling (device)) + continue; + device_array[n++] = device->priv->device_file; } -- 1.7.4.1