From 67f01bc9a42ca71b0f23ab3c6b43c376e520cadf Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 2 May 2022 16:27:22 -0400 Subject: [PATCH] file monitor fix Resolves: #2079308 --- ...er-Properly-detect-fanotify-failures.patch | 251 ++++++++++++++++++ tracker-miners.spec | 7 +- 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 0001-libtracker-miner-Properly-detect-fanotify-failures.patch diff --git a/0001-libtracker-miner-Properly-detect-fanotify-failures.patch b/0001-libtracker-miner-Properly-detect-fanotify-failures.patch new file mode 100644 index 0000000..ab412e9 --- /dev/null +++ b/0001-libtracker-miner-Properly-detect-fanotify-failures.patch @@ -0,0 +1,251 @@ +From 94a189ee9b086c2f0105cfd80c6a61588f7ffe87 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 2 May 2022 15:05:50 -0400 +Subject: [PATCH] libtracker-miner: Properly detect fanotify failures + +commit 28142bdb5e3b96e0e7328322f3a880d97a6cdca0 makes +trackers file monitoring code fall back to GLib file monitors, +if fanotify doesn't work. + +Unfortunately, fanotify_mark failures aren't propagated up, +so the fall back code doesn't get triggered in some cases. + +This commit adds the plumbing to make the fall back code get +propagated. +--- + src/libtracker-miner/tracker-monitor-fanotify.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/libtracker-miner/tracker-monitor-fanotify.c b/src/libtracker-miner/tracker-monitor-fanotify.c +index 7da262e89..9c6755d4a 100644 +--- a/src/libtracker-miner/tracker-monitor-fanotify.c ++++ b/src/libtracker-miner/tracker-monitor-fanotify.c +@@ -80,60 +80,61 @@ typedef struct { + } HandleData; + + typedef struct { + TrackerMonitorFanotify *monitor; + GFile *file; + GBytes *handle_bytes; + /* This must be last in the struct */ + HandleData handle; + } MonitoredFile; + + enum { + ITEM_CREATED, + ITEM_UPDATED, + ITEM_ATTRIBUTE_UPDATED, + ITEM_DELETED, + ITEM_MOVED, + LAST_SIGNAL + }; + + enum { + PROP_0, + PROP_ENABLED, + PROP_LIMIT, + PROP_COUNT, + PROP_IGNORED, + }; + + static GInitableIface *initable_parent_iface = NULL; + + static void tracker_monitor_fanotify_initable_iface_init (GInitableIface *iface); ++static void monitored_file_free (MonitoredFile *data); + + G_DEFINE_TYPE_WITH_CODE (TrackerMonitorFanotify, tracker_monitor_fanotify, + TRACKER_TYPE_MONITOR_GLIB, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + tracker_monitor_fanotify_initable_iface_init)) + + static inline const char * + event_type_to_string (EventType evtype) + { + switch (evtype) { + case EVENT_CREATE: + return "CREATE"; + case EVENT_UPDATE: + return "UPDATE"; + case EVENT_ATTRIBUTES_UPDATE: + return "ATTRIBUTES_UPDATE"; + case EVENT_DELETE: + return "DELETE"; + case EVENT_MOVE: + return "MOVE"; + default: + g_assert_not_reached (); + } + } + + static void + emit_event (TrackerMonitorFanotify *monitor, + EventType evtype, + GFile *file, + GFile *other_file, +@@ -532,153 +533,161 @@ tracker_monitor_fanotify_set_property (GObject *object, + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } + } + + static void + tracker_monitor_fanotify_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + TrackerMonitorFanotify *monitor = TRACKER_MONITOR_FANOTIFY (object); + + switch (prop_id) { + case PROP_ENABLED: + g_value_set_boolean (value, monitor->enabled); + break; + case PROP_LIMIT: + g_value_set_uint (value, monitor->limit); + break; + case PROP_COUNT: + g_value_set_uint (value, tracker_monitor_get_count (TRACKER_MONITOR (object))); + break; + case PROP_IGNORED: + g_value_set_uint (value, monitor->ignored); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } + } + +-static void ++static gboolean + add_mark (TrackerMonitorFanotify *monitor, + GFile *file) + { + gchar *path; + + path = g_file_get_path (file); + + if (fanotify_mark (monitor->fanotify_fd, + (FAN_MARK_ADD | FAN_MARK_ONLYDIR), + FANOTIFY_EVENTS, + AT_FDCWD, + path) < 0) { + g_warning ("Could not add mark for path '%s': %m", path); ++ return FALSE; + } + + g_free (path); ++ return TRUE; + } + + static void + remove_mark (TrackerMonitorFanotify *monitor, + GFile *file) + { + gchar *path; + + path = g_file_get_path (file); + + if (fanotify_mark (monitor->fanotify_fd, + FAN_MARK_REMOVE, + FANOTIFY_EVENTS, + AT_FDCWD, + path) < 0) { + if (errno != ENOENT) + g_warning ("Could not remove mark for path '%s': %m", path); + } + + g_free (path); + } + + static MonitoredFile * + monitored_file_new (TrackerMonitorFanotify *monitor, + GFile *file) + { + MonitoredFile *data; + gchar *path; + struct statfs buf; + int mntid; ++ gboolean mark_added = FALSE; + + path = g_file_get_path (file); + + if (statfs (path, &buf) < 0) { + if (errno != ENOENT) + g_warning ("Could not get filesystem ID for %s: %m", path); + g_free (path); + return NULL; + } + + retry: + /* We need to try different sizes for the file_handle data */ + data = g_slice_alloc0 (sizeof (MonitoredFile) + monitor->file_handle_payload); + data->handle.handle.handle_bytes = monitor->file_handle_payload; + + if (name_to_handle_at (AT_FDCWD, path, + (void *) &data->handle.handle, + &mntid, + 0) < 0) { + if (errno == EOVERFLOW) { + ssize_t payload; + + /* The payload is not big enough to hold a file_handle, + * in this case we get the ideal handle data size, so + * fetch that and retry. + */ + payload = data->handle.handle.handle_bytes; + g_slice_free1 (sizeof (MonitoredFile) + monitor->file_handle_payload, data); + monitor->file_handle_payload = payload; + goto retry; + } else if (errno != ENOENT) { + g_warning ("Could not get file handle for '%s': %m", path); + } + + g_free (path); + return NULL; + } + + data->file = g_object_ref (file); + data->monitor = monitor; + memcpy (&data->handle.fsid, &buf.f_fsid, sizeof(fsid_t)); +- add_mark (monitor, file); ++ mark_added = add_mark (monitor, file); + g_free (path); + + data->handle_bytes = create_bytes_for_handle (&data->handle); + ++ if (!mark_added) { ++ monitored_file_free (data); ++ data = NULL; ++ } ++ + return data; + } + + static void + monitored_file_free (MonitoredFile *data) + { + if (!data) + return; + + g_bytes_unref (data->handle_bytes); + remove_mark (data->monitor, data->file); + g_object_unref (data->file); + g_slice_free1 (sizeof (MonitoredFile) + + data->handle.handle.handle_bytes, data); + } + + static gboolean + tracker_monitor_fanotify_add (TrackerMonitor *object, + GFile *file) + { + TrackerMonitorFanotify *monitor = TRACKER_MONITOR_FANOTIFY (object); + MonitoredFile *data; + + if (g_hash_table_contains (monitor->monitored_dirs, file)) + return TRUE; + + if (g_hash_table_size (monitor->monitored_dirs) > monitor->limit) { + monitor->ignored++; + return FALSE; + } +-- +2.35.1 + diff --git a/tracker-miners.spec b/tracker-miners.spec index 9659fc3..4d51791 100644 --- a/tracker-miners.spec +++ b/tracker-miners.spec @@ -24,13 +24,14 @@ Name: tracker-miners Version: 3.3.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Tracker miners and metadata extractors # libtracker-extract and libtracker-miner libraries are LGPLv2+; the miners are a mix of GPLv2+ and LGPLv2+ code License: GPLv2+ and LGPLv2+ URL: https://gnome.pages.gitlab.gnome.org/tracker/ Source0: https://download.gnome.org/sources/tracker-miners/3.3/tracker-miners-%{tarball_version}.tar.xz +Patch0: 0001-libtracker-miner-Properly-detect-fanotify-failures.patch BuildRequires: asciidoc BuildRequires: gcc @@ -157,6 +158,10 @@ This package contains various miners and metadata extractors for tracker. %changelog +* Mon May 02 2022 Ray Strode - 3.3.0-2 +- file monitor fix + Resolves: #2079308 + * Sun Mar 20 2022 David King - 3.3.0-1 - Update to 3.3.0