From 03d8ee1a95a49d386b564054858001143300192a 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. This can be disabled by setting ENV{UDISKS_DISABLE_KERNEL_POLLING}="1" in an udisks rule. Preparation for bug #34710. --- src/device-private.h | 5 +++ src/poller.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 0 deletions(-) diff --git a/src/device-private.h b/src/device-private.h index a6db7f2..160ff65 100644 --- a/src/device-private.h +++ b/src/device-private.h @@ -59,6 +59,11 @@ struct DevicePrivate gboolean job_is_cancellable; double job_percentage; + gboolean checked_in_kernel_polling_support; + gboolean using_in_kernel_polling; + gboolean supports_media_change_event; + gboolean supports_eject_request_event; + guint linux_md_poll_timeout_id; /* A list of current polling inhibitors (Inhibitor objects) */ diff --git a/src/poller.c b/src/poller.c index 9517b5d..f518617 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,80 @@ poller_setup (int argc, /* ---------------------------------------------------------------------------------------------------- */ +static void +enable_in_kernel_polling (Device* d) +{ + /* enable in-kernel polling */ + if (g_udev_device_get_sysfs_attr_as_int (d->priv->d, "events_poll_msecs") <= 0) + { + int fd; + gchar *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 + } + 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 + } +} + +static gboolean +check_and_enable_in_kernel_polling (Device* d) +{ + /* only check once */ + if (!d->priv->checked_in_kernel_polling_support) + { + const char *supported_events; + 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")) + d->priv->supports_eject_request_event = TRUE; + + if (strstr (supported_events, "media_change")) + { + d->priv->supports_media_change_event = TRUE; + + /* Allow udev rules to disable in-kernel polling */ + if (g_udev_device_get_property_as_boolean (d->priv->d, "UDISKS_DISABLE_KERNEL_POLLING")) + { + d->priv->using_in_kernel_polling = FALSE; +#ifdef POLL_SHOW_DEBUG + g_print("**** POLLER (%d): In-kernel polling for %s disabled with UDISKS_DISABLE_KERNEL_POLLING\n", getpid (), d->priv->device_file); +#endif + } + else + { + d->priv->using_in_kernel_polling = TRUE; + enable_in_kernel_polling (d); + } + } + + d->priv->checked_in_kernel_polling_support = TRUE; + } + + return d->priv->supports_media_change_event && d->priv->using_in_kernel_polling; +} + +/* ---------------------------------------------------------------------------------------------------- */ + void poller_set_devices (GList *devices) { @@ -320,6 +395,9 @@ poller_set_devices (GList *devices) { Device *device = DEVICE (l->data); + if (check_and_enable_in_kernel_polling (device)) + continue; + device_array[n++] = device->priv->device_file; } -- 1.7.5.4