diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2011-05-09 14:47:41 +0200 |
---|---|---|
committer | Arnel A. Borja <arnelborja@src.gnome.org> | 2013-08-31 00:56:46 +0800 |
commit | 36b501bf4e4a430fb86e47535d048362f487b5e3 (patch) | |
tree | e0a7814c108edaa9f46369e02f015808d26550a6 | |
parent | 9eed9cff52b4b2f054659651aaee06dc3acc4f72 (diff) | |
download | libmediaart-36b501bf4e4a430fb86e47535d048362f487b5e3.tar.gz |
libtracker-miner: Add watchdog for failed unmounts
Fixes NB#248873. If, for whatever reason, an unmount operation fails
or doesn't respond in a timely fashion, TrackerStorage will emit
::mount-point-added again so Tracker keeps monitoring any further
change in there.
-rw-r--r-- | src/libtracker-miner/tracker-storage.c | 89 |
1 files changed, 83 insertions, 6 deletions
diff --git a/src/libtracker-miner/tracker-storage.c b/src/libtracker-miner/tracker-storage.c index f874aba..d30dc0f 100644 --- a/src/libtracker-miner/tracker-storage.c +++ b/src/libtracker-miner/tracker-storage.c @@ -47,11 +47,13 @@ typedef struct { GNode *mounts; GHashTable *mounts_by_uuid; + GHashTable *unmount_watchdogs; } TrackerStoragePrivate; typedef struct { gchar *mount_point; gchar *uuid; + guint unmount_timer_id; guint removable : 1; guint optical : 1; } MountInfo; @@ -67,6 +69,11 @@ typedef struct { gboolean exact_match; } GetRoots; +typedef struct { + TrackerStorage *storage; + GMount *mount; +} UnmountCheckData; + static void tracker_storage_finalize (GObject *object); static gboolean mount_info_free (GNode *node, gpointer user_data); @@ -78,6 +85,9 @@ static void mount_added_cb (GVolumeMonitor *monitor, static void mount_removed_cb (GVolumeMonitor *monitor, GMount *mount, gpointer user_data); +static void mount_pre_removed_cb (GVolumeMonitor *monitor, + GMount *mount, + gpointer user_data); enum { MOUNT_POINT_ADDED, @@ -143,6 +153,8 @@ tracker_storage_init (TrackerStorage *storage) g_str_equal, (GDestroyNotify) g_free, NULL); + priv->unmount_watchdogs = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_source_remove); priv->volume_monitor = g_volume_monitor_get (); @@ -150,7 +162,7 @@ tracker_storage_init (TrackerStorage *storage) g_signal_connect_object (priv->volume_monitor, "mount-removed", G_CALLBACK (mount_removed_cb), storage, 0); g_signal_connect_object (priv->volume_monitor, "mount-pre-unmount", - G_CALLBACK (mount_removed_cb), storage, 0); + G_CALLBACK (mount_pre_removed_cb), storage, 0); g_signal_connect_object (priv->volume_monitor, "mount-added", G_CALLBACK (mount_added_cb), storage, 0); @@ -169,6 +181,8 @@ tracker_storage_finalize (GObject *object) priv = TRACKER_STORAGE_GET_PRIVATE (object); + g_hash_table_destroy (priv->unmount_watchdogs); + if (priv->mounts_by_uuid) { g_hash_table_unref (priv->mounts_by_uuid); } @@ -717,11 +731,9 @@ mount_added_cb (GVolumeMonitor *monitor, } static void -mount_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data) +mount_remove (TrackerStorage *storage, + GMount *mount) { - TrackerStorage *storage; TrackerStoragePrivate *priv; MountInfo *info; GNode *node; @@ -730,7 +742,6 @@ mount_removed_cb (GVolumeMonitor *monitor, gchar *mount_point; gchar *mp; - storage = user_data; priv = TRACKER_STORAGE_GET_PRIVATE (storage); file = g_mount_get_root (mount); @@ -764,6 +775,72 @@ mount_removed_cb (GVolumeMonitor *monitor, g_object_unref (file); } +static void +mount_removed_cb (GVolumeMonitor *monitor, + GMount *mount, + gpointer user_data) +{ + TrackerStorage *storage; + TrackerStoragePrivate *priv; + + storage = user_data; + priv = TRACKER_STORAGE_GET_PRIVATE (storage); + + mount_remove (storage, mount); + + /* Unmount suceeded, remove the pending check */ + g_hash_table_remove (priv->unmount_watchdogs, mount); +} + +static gboolean +unmount_failed_cb (gpointer user_data) +{ + UnmountCheckData *data = user_data; + TrackerStoragePrivate *priv; + + /* If this timeout gets to be executed, this is due + * to a pre-unmount signal with no corresponding + * unmount in a timely fashion, we assume this is + * due to an error, and add back the still mounted + * path. + */ + priv = TRACKER_STORAGE_GET_PRIVATE (data->storage); + + g_warning ("Unmount operation failed, adding back mount point..."); + + mount_add (data->storage, data->mount); + + g_hash_table_remove (priv->unmount_watchdogs, data->mount); + return FALSE; +} + +static void +mount_pre_removed_cb (GVolumeMonitor *monitor, + GMount *mount, + gpointer user_data) +{ + TrackerStorage *storage; + TrackerStoragePrivate *priv; + UnmountCheckData *data; + guint id; + + storage = user_data; + priv = TRACKER_STORAGE_GET_PRIVATE (storage); + + mount_remove (storage, mount); + + /* Add check for failed unmounts */ + data = g_new (UnmountCheckData, 1); + data->storage = storage; + data->mount = mount; + + id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 1, + unmount_failed_cb, + data, (GDestroyNotify) g_free); + g_hash_table_insert (priv->unmount_watchdogs, data->mount, + GUINT_TO_POINTER (id)); +} + /** * tracker_storage_new: * |