67f01bc9a4
Resolves: #2079308
252 lines
6.6 KiB
Diff
252 lines
6.6 KiB
Diff
From 94a189ee9b086c2f0105cfd80c6a61588f7ffe87 Mon Sep 17 00:00:00 2001
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
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
|
|
|