From 40b36069323b64ddd8c5a944d8a74f79b624b438 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Tue, 5 Apr 2011 21:13:32 +0200 Subject: [PATCH 5/5] Force media validation on media change for in-kernel polling mode When using the in-kernel poller the partition revalidation bug https://bugzilla.kernel.org/show_bug.cgi?id=13029 still happens when removing media from a drive (such as SD card readers). Work around this by applying the same "open with O_NONBLOCK" trick that the continuous poller already does. Also add a comment to poller_poll_device() why the weird double-open with O_NONBLOCK is necessary. --- src/daemon.c | 9 +++++++++ src/poller.c | 21 +++++++++++++++++++++ src/poller.h | 3 +++ 3 files changed, 33 insertions(+), 0 deletions(-) diff --git a/src/daemon.c b/src/daemon.c index 0ba791d..f5bdc14 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -1069,6 +1069,15 @@ block_device_changed (Daemon *daemon, daemon_local_update_poller (daemon); daemon_local_update_spindown (daemon); } + + /* work around the kernel not properly validating partitions after block + * device changes (like media removals for SD cards); see + * https://bugzilla.kernel.org/show_bug.cgi?id=13029 */ + if (device->priv->supports_media_change_event && g_udev_device_get_property (d, "DISK_MEDIA_CHANGE")) + { + g_print ("**** DISK_MEDIA_CHANGE event on %s, re-checking for media\n", device->priv->device_file); + poller_check_media (device); + } } else { diff --git a/src/poller.c b/src/poller.c index a75bacc..8c7a7d8 100644 --- a/src/poller.c +++ b/src/poller.c @@ -136,6 +136,9 @@ poller_poll_device (const gchar *device_file) } else { + /* we need to use O_NONBLOCK here to cause partition devices to go + * away after media removal; that won't fail with ENOMEDIA. + * See https://bugzilla.kernel.org/show_bug.cgi?id=13029 */ fd = open (device_file, O_RDONLY); fd2 = open (device_file, O_RDONLY | O_NONBLOCK); if (fd != -1) @@ -258,6 +261,10 @@ poller_have_data (GIOChannel *channel, poller_do_lock_cdtray (tokens[1], atoi (tokens[0])); g_strfreev (tokens); } + else if (g_str_has_prefix (line, "check-media:")) + { + poller_poll_device (line + strlen ("check-media:")); + } else { g_printerr ("**** POLLER (%d): unknown command '%s'\n", getpid (), line); @@ -462,3 +469,17 @@ poller_lock_cdtray (Device* device, gboolean lock) } /* ---------------------------------------------------------------------------------------------------- */ + +void poller_check_media (Device* device) +{ + gchar *command; + + command = g_strconcat ("check-media:", device->priv->device_file, "\n", NULL); +#ifdef POLL_SHOW_DEBUG + g_print ("**** POLLER (%d): Sending media check command: '%s'\n", getpid (), command); +#endif + if (write (poller_daemon_write_end_fd, command, strlen (command)) < 0) + g_error ("**** POLLER (%d): Failed to send media check command: %s", getpid (), g_strerror (errno)); +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/poller.h b/src/poller.h index 67eb9fc..ae130ce 100644 --- a/src/poller.h +++ b/src/poller.h @@ -31,4 +31,7 @@ void poller_set_devices (GList *devices); /* CD tray handling; moved to poller as it could block for a longer time */ void poller_lock_cdtray (Device* device, gboolean lock); +/* One-time check for media or updated/removed partitions on a device */ +void poller_check_media (Device* device); + #endif /* __POLLER_H */ -- 1.7.4.1