Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,43 +0,0 @@
|
||||
From d1ab5870e828df259897598298c2ca66b587426a Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 29 Aug 2018 15:36:57 +0200
|
||||
Subject: [PATCH] backend: Prevent usage of NULL
|
||||
|
||||
g_dbus_connection_get_peer_credentials may fail in some cases, see
|
||||
the documentation, and thus we have to check the return value before
|
||||
use in order to prevent warnings like the following:
|
||||
|
||||
g_credentials_get_unix_pid: assertion 'G_IS_CREDENTIALS (credentials)' failed
|
||||
|
||||
Print simply -1 if pid can't be obtained this way.
|
||||
---
|
||||
daemon/gvfsbackend.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
|
||||
index 673070fa..4fd3455c 100644
|
||||
--- a/daemon/gvfsbackend.c
|
||||
+++ b/daemon/gvfsbackend.c
|
||||
@@ -609,14 +609,17 @@ g_vfs_backend_invocation_first_handler (GVfsDBusMount *object,
|
||||
{
|
||||
GDBusConnection *connection;
|
||||
GCredentials *credentials;
|
||||
+ pid_t pid = -1;
|
||||
|
||||
connection = g_dbus_method_invocation_get_connection (invocation);
|
||||
credentials = g_dbus_connection_get_peer_credentials (connection);
|
||||
+ if (credentials)
|
||||
+ pid = g_credentials_get_unix_pid (credentials, NULL);
|
||||
|
||||
- g_debug ("backend_dbus_handler %s:%s (pid=%u)\n",
|
||||
+ g_debug ("backend_dbus_handler %s:%s (pid=%ld)\n",
|
||||
g_dbus_method_invocation_get_interface_name (invocation),
|
||||
g_dbus_method_invocation_get_method_name (invocation),
|
||||
- g_credentials_get_unix_pid (credentials, NULL));
|
||||
+ (long)pid);
|
||||
|
||||
if (backend->priv->block_requests)
|
||||
{
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From 9e38c56f99372b2474a780ac0c7c7d9b38e490cf Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Mon, 11 May 2026 17:48:26 +0200
|
||||
Subject: [PATCH] daemon: Add process name to debug handler log
|
||||
|
||||
Made-with: Cursor (Claude)
|
||||
---
|
||||
daemon/gvfsbackend.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
|
||||
index fa1389ea..7dfd5300 100644
|
||||
--- a/daemon/gvfsbackend.c
|
||||
+++ b/daemon/gvfsbackend.c
|
||||
@@ -636,16 +636,25 @@ g_vfs_backend_invocation_first_handler (GVfsDBusMount *object,
|
||||
GDBusConnection *connection;
|
||||
GCredentials *credentials;
|
||||
pid_t pid = -1;
|
||||
+ g_autofree gchar *comm = NULL;
|
||||
|
||||
connection = g_dbus_method_invocation_get_connection (invocation);
|
||||
credentials = g_dbus_connection_get_peer_credentials (connection);
|
||||
if (credentials)
|
||||
pid = g_credentials_get_unix_pid (credentials, NULL);
|
||||
|
||||
- g_debug ("backend_dbus_handler %s:%s (pid=%ld)\n",
|
||||
- g_dbus_method_invocation_get_interface_name (invocation),
|
||||
- g_dbus_method_invocation_get_method_name (invocation),
|
||||
- (long)pid);
|
||||
+ if (pid > 0)
|
||||
+ {
|
||||
+ g_autofree gchar *comm_path = g_strdup_printf ("/proc/%ld/comm", (long)pid);
|
||||
+
|
||||
+ if (g_file_get_contents (comm_path, &comm, NULL, NULL))
|
||||
+ g_strstrip (comm);
|
||||
+ }
|
||||
+
|
||||
+ g_debug ("backend_dbus_handler %s:%s (pid=%ld comm=%s)\n",
|
||||
+ g_dbus_method_invocation_get_interface_name (invocation),
|
||||
+ g_dbus_method_invocation_get_method_name (invocation),
|
||||
+ (long)pid, comm ? comm : "");
|
||||
|
||||
if (backend->priv->block_requests)
|
||||
{
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
From 1d4acb8d95612384f603aa5c0c8d20060010fbc7 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 1 Aug 2024 12:35:43 +0200
|
||||
Subject: [PATCH] daemon: Add support for edit mode
|
||||
|
||||
Currently, it is impossible to open the output stream without truncating
|
||||
the file or appending it. This is a problem for many POSIX applications
|
||||
relying on our FUSE daemon. Let's add an edit mode that could be used for
|
||||
this purpose.
|
||||
|
||||
Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249
|
||||
---
|
||||
daemon/gvfsbackend.h | 8 ++++++++
|
||||
daemon/gvfsjobopenforwrite.c | 23 +++++++++++++++++++++++
|
||||
daemon/gvfsjobopenforwrite.h | 3 ++-
|
||||
3 files changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h
|
||||
index 9c7476cf..0f97cff6 100644
|
||||
--- a/daemon/gvfsbackend.h
|
||||
+++ b/daemon/gvfsbackend.h
|
||||
@@ -211,6 +211,14 @@ struct _GVfsBackendClass
|
||||
const char *etag,
|
||||
gboolean make_backup,
|
||||
GFileCreateFlags flags);
|
||||
+ gboolean (*try_edit) (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags);
|
||||
+ void (*edit) (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags);
|
||||
void (*close_write) (GVfsBackend *backend,
|
||||
GVfsJobCloseWrite *job,
|
||||
GVfsBackendHandle handle);
|
||||
diff --git a/daemon/gvfsjobopenforwrite.c b/daemon/gvfsjobopenforwrite.c
|
||||
index 439b63c4..5b6e8033 100644
|
||||
--- a/daemon/gvfsjobopenforwrite.c
|
||||
+++ b/daemon/gvfsjobopenforwrite.c
|
||||
@@ -220,6 +220,20 @@ run (GVfsJob *job)
|
||||
op_job->make_backup,
|
||||
op_job->flags);
|
||||
}
|
||||
+ else if (op_job->mode == OPEN_FOR_WRITE_EDIT)
|
||||
+ {
|
||||
+ if (class->edit == NULL)
|
||||
+ {
|
||||
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
+ _("Operation not supported"));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ class->edit (op_job->backend,
|
||||
+ op_job,
|
||||
+ op_job->filename,
|
||||
+ op_job->flags);
|
||||
+ }
|
||||
else
|
||||
g_assert_not_reached (); /* Handled in try */
|
||||
}
|
||||
@@ -259,6 +273,15 @@ try (GVfsJob *job)
|
||||
op_job->make_backup,
|
||||
op_job->flags);
|
||||
}
|
||||
+ else if (op_job->mode == OPEN_FOR_WRITE_EDIT)
|
||||
+ {
|
||||
+ if (class->try_edit == NULL)
|
||||
+ return FALSE;
|
||||
+ return class->try_edit (op_job->backend,
|
||||
+ op_job,
|
||||
+ op_job->filename,
|
||||
+ op_job->flags);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
GError *error = NULL;
|
||||
diff --git a/daemon/gvfsjobopenforwrite.h b/daemon/gvfsjobopenforwrite.h
|
||||
index 141189f3..e070d0ea 100644
|
||||
--- a/daemon/gvfsjobopenforwrite.h
|
||||
+++ b/daemon/gvfsjobopenforwrite.h
|
||||
@@ -41,7 +41,8 @@ typedef struct _GVfsJobOpenForWriteClass GVfsJobOpenForWriteClass;
|
||||
typedef enum {
|
||||
OPEN_FOR_WRITE_CREATE = 0,
|
||||
OPEN_FOR_WRITE_APPEND = 1,
|
||||
- OPEN_FOR_WRITE_REPLACE = 2
|
||||
+ OPEN_FOR_WRITE_REPLACE = 2,
|
||||
+ OPEN_FOR_WRITE_EDIT = 3
|
||||
} GVfsJobOpenForWriteMode;
|
||||
|
||||
typedef enum {
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From fabacfef29e24628f7a1a303be4b54cb006431bb Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 1 Aug 2024 12:40:15 +0200
|
||||
Subject: [PATCH] fuse: Use edit mode instead of returning ENOTSUP
|
||||
|
||||
Currently, the FUSE daemon fails with the `ENOTSUP` error when opening
|
||||
a file for writing without `O_APPEND` or `O_TRUNC`. This is a problem
|
||||
for many POSIX applications. Let's try the newly added edit mode instead.
|
||||
|
||||
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249
|
||||
---
|
||||
client/gvfsfusedaemon.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
|
||||
index ff5641ae..9ec4e3d8 100644
|
||||
--- a/client/gvfsfusedaemon.c
|
||||
+++ b/client/gvfsfusedaemon.c
|
||||
@@ -1003,6 +1003,8 @@ setup_input_stream (GFile *file, FileHandle *fh)
|
||||
return result;
|
||||
}
|
||||
|
||||
+#define _g_file_edit(file, flags, cancellable, error) g_file_append_to(file, flags | (1 << 15), cancellable, error)
|
||||
+
|
||||
static gint
|
||||
setup_output_stream (GFile *file, FileHandle *fh, int flags)
|
||||
{
|
||||
@@ -1032,7 +1034,7 @@ setup_output_stream (GFile *file, FileHandle *fh, int flags)
|
||||
else if (flags & O_APPEND)
|
||||
fh->stream = g_file_append_to (file, 0, NULL, &error);
|
||||
else
|
||||
- result = -ENOTSUP;
|
||||
+ fh->stream = _g_file_edit (file, 0, NULL, &error);
|
||||
if (fh->stream)
|
||||
fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream));
|
||||
}
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
From 5dd5f5b97bc753cdf32a04e3de4bddce651ceb9b Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 1 Aug 2024 12:39:49 +0200
|
||||
Subject: [PATCH] gdaemonfile: Use edit mode when private edit flag is used
|
||||
|
||||
The newly added edit mode is meant only for private use by our FUSE
|
||||
daemon. Let's add a new private flag for the append operation to enable
|
||||
the edit mode.
|
||||
---
|
||||
client/gdaemonfile.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c
|
||||
index 485698b2..d66d0934 100644
|
||||
--- a/client/gdaemonfile.c
|
||||
+++ b/client/gdaemonfile.c
|
||||
@@ -57,6 +57,8 @@ G_DEFINE_TYPE_WITH_CODE (GDaemonFile, g_daemon_file, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
|
||||
g_daemon_file_file_iface_init))
|
||||
|
||||
+#define PRIVATE_EDIT_FLAG (1 << 15)
|
||||
+
|
||||
static void
|
||||
g_daemon_file_finalize (GObject *object)
|
||||
{
|
||||
@@ -1198,7 +1200,10 @@ g_daemon_file_append_to (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
- return file_open_write (file, 1, "", FALSE, flags, cancellable, error);
|
||||
+ if (flags & PRIVATE_EDIT_FLAG)
|
||||
+ return file_open_write (file, 3, "", FALSE, flags, cancellable, error);
|
||||
+ else
|
||||
+ return file_open_write (file, 1, "", FALSE, flags, cancellable, error);
|
||||
}
|
||||
|
||||
static GFileOutputStream *
|
||||
@@ -3130,7 +3135,10 @@ g_daemon_file_append_to_async (GFile *file,
|
||||
g_task_set_source_tag (task, g_daemon_file_append_to_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
- file_open_write_async (file, task, 1, "", FALSE, flags);
|
||||
+ if (flags & PRIVATE_EDIT_FLAG)
|
||||
+ file_open_write_async (file, task, 3, "", FALSE, flags);
|
||||
+ else
|
||||
+ file_open_write_async (file, task, 1, "", FALSE, flags);
|
||||
}
|
||||
|
||||
static GFileOutputStream *
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
From b17f15558194ab3025c8a5cb1a2767c54333f28e Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 13 Nov 2024 11:22:27 +0100
|
||||
Subject: [PATCH] smb: Disable seek support when appening
|
||||
|
||||
The seek is currently enabled when appending. However, the libsmbclient
|
||||
doesn't support O_APPEND flag property [1]. The offset is not reset after
|
||||
seeking. Let's disable seek support when appending to deal with it. The
|
||||
seek operation doesn't make sense when appening anyway.
|
||||
|
||||
[1] https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183
|
||||
---
|
||||
daemon/gvfsbackendsmb.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
|
||||
index dafbb71c..c2075555 100644
|
||||
--- a/daemon/gvfsbackendsmb.c
|
||||
+++ b/daemon/gvfsbackendsmb.c
|
||||
@@ -871,7 +871,12 @@ do_append_to (GVfsBackend *backend,
|
||||
handle->file = file;
|
||||
|
||||
g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
- g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
+
|
||||
+ /* The O_APPEND flag is not properly supported by the libsmbclient library
|
||||
+ * when seeking. See:
|
||||
+ * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183
|
||||
+ */
|
||||
+ g_vfs_job_open_for_write_set_can_seek (job, FALSE);
|
||||
g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
g_vfs_job_open_for_write_set_handle (job, handle);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
From 885bcc18b65ebd6d3c5bac56994f9f631cb9d363 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 6 Nov 2024 14:58:18 +0100
|
||||
Subject: [PATCH] smb: Fail when initial_offset can't be determined
|
||||
|
||||
Currently, when the initial_offset can't be determined, the seek and
|
||||
truncate operations are disabled. Let's fail immediatelly instead to
|
||||
simplify the code as a preparation for the follow-up changes. Just a
|
||||
note tha this situation can't happen with the current libsmbclient
|
||||
codebase.
|
||||
---
|
||||
daemon/gvfsbackendsmb.c | 22 ++++++++++++----------
|
||||
1 file changed, 12 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
|
||||
index c1c2d5f0..dafbb71c 100644
|
||||
--- a/daemon/gvfsbackendsmb.c
|
||||
+++ b/daemon/gvfsbackendsmb.c
|
||||
@@ -857,20 +857,22 @@ do_append_to (GVfsBackend *backend,
|
||||
g_vfs_job_failed_from_errno (G_VFS_JOB (job), fixup_open_errno (errno));
|
||||
else
|
||||
{
|
||||
- handle = g_new0 (SmbWriteHandle, 1);
|
||||
- handle->file = file;
|
||||
-
|
||||
smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
|
||||
initial_offset = smbc_lseek (op_backend->smb_context, file,
|
||||
0, SEEK_CUR);
|
||||
if (initial_offset == (off_t) -1)
|
||||
- g_vfs_job_open_for_write_set_can_seek (job, FALSE);
|
||||
- else
|
||||
- {
|
||||
- g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
- g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
- g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
- }
|
||||
+ {
|
||||
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job),
|
||||
+ fixup_open_errno (errno));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ handle = g_new0 (SmbWriteHandle, 1);
|
||||
+ handle->file = file;
|
||||
+
|
||||
+ g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
+ g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
g_vfs_job_open_for_write_set_handle (job, handle);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
}
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
From b4ff6ddb32296f43439b4be79c7864f7ae7d14f1 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 13 Nov 2024 11:34:19 +0100
|
||||
Subject: [PATCH] smb: Fix offset after truncate when appending
|
||||
|
||||
The truncate operation is currently enabled when appending. However,
|
||||
the libsmbclient doesn't support O_APPEND flag property [1]. The
|
||||
offset is not reset after the truncate operation. This may lead to
|
||||
data corruptions. Let's explicitely seek to the desired offset when
|
||||
truncating to prevent this.
|
||||
|
||||
[1] https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183
|
||||
---
|
||||
daemon/gvfsbackendsmb.c | 27 ++++++++++++++++++++++++---
|
||||
1 file changed, 24 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
|
||||
index c2075555..f287264b 100644
|
||||
--- a/daemon/gvfsbackendsmb.c
|
||||
+++ b/daemon/gvfsbackendsmb.c
|
||||
@@ -780,6 +780,7 @@ typedef struct {
|
||||
char *uri;
|
||||
char *tmp_uri;
|
||||
char *backup_uri;
|
||||
+ GVfsJobOpenForWriteMode mode;
|
||||
} SmbWriteHandle;
|
||||
|
||||
static void
|
||||
@@ -824,6 +825,7 @@ do_create (GVfsBackend *backend,
|
||||
{
|
||||
handle = g_new0 (SmbWriteHandle, 1);
|
||||
handle->file = file;
|
||||
+ handle->mode = job->mode;
|
||||
|
||||
g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
@@ -869,6 +871,7 @@ do_append_to (GVfsBackend *backend,
|
||||
|
||||
handle = g_new0 (SmbWriteHandle, 1);
|
||||
handle->file = file;
|
||||
+ handle->mode = job->mode;
|
||||
|
||||
g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
|
||||
@@ -1141,6 +1144,7 @@ do_replace (GVfsBackend *backend,
|
||||
handle->uri = uri;
|
||||
handle->tmp_uri = tmp_uri;
|
||||
handle->backup_uri = backup_uri;
|
||||
+ handle->mode = job->mode;
|
||||
|
||||
g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
@@ -1229,9 +1233,26 @@ do_truncate (GVfsBackend *backend,
|
||||
|
||||
smbc_ftruncate = smbc_getFunctionFtruncate (op_backend->smb_context);
|
||||
if (smbc_ftruncate (op_backend->smb_context, handle->file, size) == -1)
|
||||
- g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
|
||||
- else
|
||||
- g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
+ {
|
||||
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (handle->mode == OPEN_FOR_WRITE_APPEND)
|
||||
+ {
|
||||
+ smbc_lseek_fn smbc_lseek;
|
||||
+ off_t res;
|
||||
+
|
||||
+ smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
|
||||
+ res = smbc_lseek (op_backend->smb_context, handle->file, size, SEEK_SET);
|
||||
+ if (res == (off_t)-1)
|
||||
+ {
|
||||
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,177 +0,0 @@
|
||||
From bcbf85cc1f9bd8c1cb673a5d7d3f9907d84e3caa Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 13 Nov 2024 11:52:28 +0100
|
||||
Subject: [PATCH] smb: Implement support for edit mode
|
||||
|
||||
Implement support for the newly added edit mode in the SMB backend.
|
||||
|
||||
Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249
|
||||
---
|
||||
daemon/gvfsbackendsmb.c | 109 +++++++++++++++++++---------------------
|
||||
1 file changed, 53 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
|
||||
index f287264b..4fbdfd23 100644
|
||||
--- a/daemon/gvfsbackendsmb.c
|
||||
+++ b/daemon/gvfsbackendsmb.c
|
||||
@@ -793,10 +793,11 @@ smb_write_handle_free (SmbWriteHandle *handle)
|
||||
}
|
||||
|
||||
static void
|
||||
-do_create (GVfsBackend *backend,
|
||||
- GVfsJobOpenForWrite *job,
|
||||
- const char *filename,
|
||||
- GFileCreateFlags flags)
|
||||
+open_for_write (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags,
|
||||
+ int open_flags)
|
||||
{
|
||||
GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
|
||||
char *uri;
|
||||
@@ -804,12 +805,12 @@ do_create (GVfsBackend *backend,
|
||||
SmbWriteHandle *handle;
|
||||
smbc_open_fn smbc_open;
|
||||
int errsv;
|
||||
+ off_t initial_offset = 0;
|
||||
|
||||
uri = create_smb_uri (op_backend->server, op_backend->port, op_backend->share, filename);
|
||||
smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
|
||||
errno = 0;
|
||||
- file = smbc_open (op_backend->smb_context, uri,
|
||||
- O_CREAT|O_RDWR|O_EXCL, 0666);
|
||||
+ file = smbc_open (op_backend->smb_context, uri, open_flags, 0666);
|
||||
g_free (uri);
|
||||
|
||||
if (file == NULL)
|
||||
@@ -817,48 +818,16 @@ do_create (GVfsBackend *backend,
|
||||
errsv = fixup_open_errno (errno);
|
||||
|
||||
/* We guarantee EEXIST on create on existing dir */
|
||||
- if (errsv == EISDIR)
|
||||
+ if (job->mode == OPEN_FOR_WRITE_CREATE && errsv == EISDIR)
|
||||
errsv = EEXIST;
|
||||
g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
|
||||
+ return;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- handle = g_new0 (SmbWriteHandle, 1);
|
||||
- handle->file = file;
|
||||
- handle->mode = job->mode;
|
||||
-
|
||||
- g_vfs_job_open_for_write_set_can_seek (job, TRUE);
|
||||
- g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
- g_vfs_job_open_for_write_set_handle (job, handle);
|
||||
- g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
- }
|
||||
-}
|
||||
|
||||
-static void
|
||||
-do_append_to (GVfsBackend *backend,
|
||||
- GVfsJobOpenForWrite *job,
|
||||
- const char *filename,
|
||||
- GFileCreateFlags flags)
|
||||
-{
|
||||
- GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
|
||||
- char *uri;
|
||||
- SMBCFILE *file;
|
||||
- SmbWriteHandle *handle;
|
||||
- off_t initial_offset;
|
||||
- smbc_open_fn smbc_open;
|
||||
- smbc_lseek_fn smbc_lseek;
|
||||
-
|
||||
- uri = create_smb_uri (op_backend->server, op_backend->port, op_backend->share, filename);
|
||||
- smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
|
||||
- errno = 0;
|
||||
- file = smbc_open (op_backend->smb_context, uri,
|
||||
- O_CREAT|O_RDWR|O_APPEND, 0666);
|
||||
- g_free (uri);
|
||||
-
|
||||
- if (file == NULL)
|
||||
- g_vfs_job_failed_from_errno (G_VFS_JOB (job), fixup_open_errno (errno));
|
||||
- else
|
||||
+ if (job->mode == OPEN_FOR_WRITE_APPEND)
|
||||
{
|
||||
+ smbc_lseek_fn smbc_lseek;
|
||||
+
|
||||
smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context);
|
||||
initial_offset = smbc_lseek (op_backend->smb_context, file,
|
||||
0, SEEK_CUR);
|
||||
@@ -868,24 +837,51 @@ do_append_to (GVfsBackend *backend,
|
||||
fixup_open_errno (errno));
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
|
||||
- handle = g_new0 (SmbWriteHandle, 1);
|
||||
- handle->file = file;
|
||||
- handle->mode = job->mode;
|
||||
+ handle = g_new0 (SmbWriteHandle, 1);
|
||||
+ handle->file = file;
|
||||
+ handle->mode = job->mode;
|
||||
|
||||
- g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
+ g_vfs_job_open_for_write_set_initial_offset (job, initial_offset);
|
||||
|
||||
- /* The O_APPEND flag is not properly supported by the libsmbclient library
|
||||
- * when seeking. See:
|
||||
- * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183
|
||||
- */
|
||||
- g_vfs_job_open_for_write_set_can_seek (job, FALSE);
|
||||
- g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
- g_vfs_job_open_for_write_set_handle (job, handle);
|
||||
- g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
- }
|
||||
+ /* The O_APPEND flag is not properly supported by the libsmbclient library
|
||||
+ * when seeking. See:
|
||||
+ * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183
|
||||
+ */
|
||||
+ g_vfs_job_open_for_write_set_can_seek (job,
|
||||
+ job->mode != OPEN_FOR_WRITE_APPEND);
|
||||
+ g_vfs_job_open_for_write_set_can_truncate (job, TRUE);
|
||||
+ g_vfs_job_open_for_write_set_handle (job, handle);
|
||||
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
}
|
||||
|
||||
+static void
|
||||
+do_create (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags)
|
||||
+{
|
||||
+ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR|O_EXCL);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_append_to (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags)
|
||||
+{
|
||||
+ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR|O_APPEND);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_edit (GVfsBackend *backend,
|
||||
+ GVfsJobOpenForWrite *job,
|
||||
+ const char *filename,
|
||||
+ GFileCreateFlags flags)
|
||||
+{
|
||||
+ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR);
|
||||
+}
|
||||
|
||||
static char *
|
||||
get_dir_from_uri (const char *uri)
|
||||
@@ -2153,6 +2149,7 @@ g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass)
|
||||
backend_class->close_read = do_close_read;
|
||||
backend_class->create = do_create;
|
||||
backend_class->append_to = do_append_to;
|
||||
+ backend_class->edit = do_edit;
|
||||
backend_class->replace = do_replace;
|
||||
backend_class->write = do_write;
|
||||
backend_class->seek_on_write = do_seek_on_write;
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
From 78cc4e391d4f9e6e17af83e980f9d819b7fd208e Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 2 Jun 2026 15:32:58 +0200
|
||||
Subject: [PATCH] trash: Add debug prints for mounts handling
|
||||
|
||||
Backport of commit e0018263.
|
||||
|
||||
Adapted for older GLib API: `g_unix_mount_entry_get_device_path`/`get_mount_path`/`get_fs_type` replaced with `g_unix_mount_get_device_path`/`g_unix_mount_get_mount_path`/`g_unix_mount_get_fs_type`.
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index fe2ee44..c195234 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -245,12 +245,22 @@ trash_watcher_remount_do (TrashWatcher *watcher)
|
||||
if (result < 0)
|
||||
{
|
||||
/* new entry. add it. */
|
||||
+ g_debug ("trash_watcher_remount_do: insert %s %s %s\n",
|
||||
+ g_unix_mount_get_device_path (new->data),
|
||||
+ g_unix_mount_get_mount_path (new->data),
|
||||
+ g_unix_mount_get_fs_type (new->data));
|
||||
+
|
||||
trash_mount_insert (watcher, &old, new->data);
|
||||
new = new->next;
|
||||
}
|
||||
else if (result > 0)
|
||||
{
|
||||
/* old entry. remove it. */
|
||||
+ g_debug ("trash_watcher_remount_do: remove %s %s %s\n",
|
||||
+ g_unix_mount_get_device_path ((*old)->mount_entry),
|
||||
+ g_unix_mount_get_mount_path ((*old)->mount_entry),
|
||||
+ g_unix_mount_get_fs_type ((*old)->mount_entry));
|
||||
+
|
||||
trash_mount_remove (old);
|
||||
}
|
||||
else
|
||||
@@ -271,6 +281,8 @@ trash_watcher_remount_timeout (gpointer user_data)
|
||||
{
|
||||
TrashWatcher *watcher = user_data;
|
||||
|
||||
+ g_debug ("trash_watcher_remount_timeout\n");
|
||||
+
|
||||
watcher->update_id = 0;
|
||||
|
||||
trash_watcher_remount_do (watcher);
|
||||
@@ -281,6 +293,8 @@ trash_watcher_remount_timeout (gpointer user_data)
|
||||
static void
|
||||
trash_watcher_remount (TrashWatcher *watcher)
|
||||
{
|
||||
+ g_debug ("trash_watcher_remount\n");
|
||||
+
|
||||
if (watcher->update_id != 0)
|
||||
return;
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
From 86805f19dbcb55a4ad6fa2a00670d00b927c9d47 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 19 Jan 2023 12:57:30 +0100
|
||||
Subject: [PATCH] trash: Add is_root function
|
||||
|
||||
Let's make the code more readable using the is_root function instead
|
||||
of char comparison.
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index 9702b860..d7ec4f77 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -44,6 +44,12 @@ struct OPAQUE_TYPE__GVfsBackendTrash
|
||||
|
||||
G_DEFINE_TYPE (GVfsBackendTrash, g_vfs_backend_trash, G_VFS_TYPE_BACKEND);
|
||||
|
||||
+static gboolean
|
||||
+is_root (const char *filename)
|
||||
+{
|
||||
+ return (filename[0] == '/' && filename[1] == '\0');
|
||||
+}
|
||||
+
|
||||
static GVfsMonitor *
|
||||
trash_backend_get_file_monitor (GVfsBackendTrash *backend,
|
||||
gboolean create)
|
||||
@@ -229,7 +235,7 @@ trash_backend_open_for_read (GVfsBackend *vfs_backend,
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
|
||||
GError *error = NULL;
|
||||
|
||||
- if (filename[1] == '\0')
|
||||
+ if (is_root (filename))
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
|
||||
_("Can’t open directory"));
|
||||
|
||||
@@ -397,7 +403,7 @@ trash_backend_delete (GVfsBackend *vfs_backend,
|
||||
GError *error = NULL;
|
||||
g_debug ("before job: %d\n", G_OBJECT(job)->ref_count);
|
||||
|
||||
- if (filename[1] == '\0')
|
||||
+ if (is_root (filename))
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
|
||||
_("The trash folder may not be deleted"));
|
||||
else
|
||||
@@ -456,7 +462,7 @@ trash_backend_pull (GVfsBackend *vfs_backend,
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
|
||||
GError *error = NULL;
|
||||
|
||||
- if (source[1] == '\0')
|
||||
+ if (is_root (source))
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("The trash folder may not be deleted"));
|
||||
else
|
||||
@@ -683,7 +689,7 @@ trash_backend_enumerate (GVfsBackend *vfs_backend,
|
||||
|
||||
trash_watcher_rescan (backend->watcher);
|
||||
|
||||
- if (filename[1])
|
||||
+ if (!is_root (filename))
|
||||
trash_backend_enumerate_non_root (backend, job, filename,
|
||||
attribute_matcher, flags);
|
||||
else
|
||||
@@ -729,7 +735,7 @@ trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
if (!backend->file_monitor && !backend->dir_monitor)
|
||||
trash_watcher_rescan (backend->watcher);
|
||||
|
||||
- if (filename[1])
|
||||
+ if (!is_root (filename))
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean is_toplevel;
|
||||
@@ -832,7 +838,7 @@ trash_backend_create_dir_monitor (GVfsBackend *vfs_backend,
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
|
||||
GVfsMonitor *monitor;
|
||||
|
||||
- if (filename[1])
|
||||
+ if (!is_root (filename))
|
||||
monitor = g_vfs_monitor_new (vfs_backend);
|
||||
else
|
||||
monitor = trash_backend_get_dir_monitor (backend, TRUE);
|
||||
@@ -853,7 +859,7 @@ trash_backend_create_file_monitor (GVfsBackend *vfs_backend,
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
|
||||
GVfsMonitor *monitor;
|
||||
|
||||
- if (filename[1])
|
||||
+ if (!is_root (filename))
|
||||
monitor = g_vfs_monitor_new (vfs_backend);
|
||||
else
|
||||
monitor = trash_backend_get_file_monitor (backend, TRUE);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
From 1c2cc7c0b80e5fc3f59e8557232bb6ff8ebbab7a Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Fri, 12 Jul 2024 13:21:49 +0200
|
||||
Subject: [PATCH] trash: Add support for x-gvfs-trash mount option
|
||||
|
||||
Currently, the trash functionality is disabled for system internal mounts.
|
||||
That might be a problem in some cases. The `x-gvfs-notrash` mount option
|
||||
allows disabling the trash functionality for certain mounts. Let's add
|
||||
support for the `x-gvfs-trash` mount option to allow the opposite.
|
||||
|
||||
See: https://issues.redhat.com/browse/RHEL-46828
|
||||
|
||||
Related: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4155
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 22 +++++++++++++---------
|
||||
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index eec32d0b..707323cb 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -218,10 +218,6 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
{
|
||||
GUnixMountPoint *mount_point = NULL;
|
||||
const gchar *mount_options;
|
||||
- gboolean retval = TRUE;
|
||||
-
|
||||
- if (g_unix_mount_is_system_internal (mount))
|
||||
- return TRUE;
|
||||
|
||||
mount_options = g_unix_mount_get_options (mount);
|
||||
if (mount_options == NULL)
|
||||
@@ -230,15 +226,23 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
NULL);
|
||||
if (mount_point != NULL)
|
||||
mount_options = g_unix_mount_point_get_options (mount_point);
|
||||
+
|
||||
+ g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
||||
}
|
||||
|
||||
- if (mount_options == NULL ||
|
||||
- strstr (mount_options, "x-gvfs-notrash") == NULL)
|
||||
- retval = FALSE;
|
||||
+ if (mount_options != NULL)
|
||||
+ {
|
||||
+ if (strstr (mount_options, "x-gvfs-trash") != NULL)
|
||||
+ return FALSE;
|
||||
|
||||
- g_clear_pointer (&mount_point, g_unix_mount_point_free);
|
||||
+ if (strstr (mount_options, "x-gvfs-notrash") != NULL)
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ if (g_unix_mount_is_system_internal (mount))
|
||||
+ return TRUE;
|
||||
|
||||
- return retval;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -1,295 +0,0 @@
|
||||
From 890b2a747bbcd9ed220fb217aba41b9ef0188ba1 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 7 Jun 2023 15:49:41 +0200
|
||||
Subject: [PATCH] trash: Add worker thread
|
||||
|
||||
The previous commit makes the backend a bit more resilience of against
|
||||
stale NFS mounts, but still a lot of I/O operations (e.g.
|
||||
`trash_watcher_rescan`) run on the main thread and can easily block the
|
||||
whole backend. This is especially problem for the `create_dir_monitor` and
|
||||
`create_file_monitor` methods that doesn't have asynchronous variants.
|
||||
This may cause hangs for nautilus, or file chooser dialog, but also for
|
||||
the whole gnome-shell session (resp. desktop-icons extension). Let's add
|
||||
a worker thread to ensure that the `create_dir_monitor` and
|
||||
`create_file_monitor` methods response immediately.
|
||||
|
||||
Related: https://bugzilla.redhat.com/show_bug.cgi?id=2152538
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 156 ++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 131 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index b4d3d089..0966242a 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -36,6 +36,10 @@ struct OPAQUE_TYPE__GVfsBackendTrash
|
||||
GVfsMonitor *file_monitor;
|
||||
GVfsMonitor *dir_monitor;
|
||||
|
||||
+ GMainContext *worker_context;
|
||||
+ GMainLoop *worker_loop;
|
||||
+ GThread *worker_thread;
|
||||
+
|
||||
TrashWatcher *watcher;
|
||||
TrashRoot *root;
|
||||
|
||||
@@ -44,6 +48,94 @@ struct OPAQUE_TYPE__GVfsBackendTrash
|
||||
|
||||
G_DEFINE_TYPE (GVfsBackendTrash, g_vfs_backend_trash, G_VFS_TYPE_BACKEND);
|
||||
|
||||
+typedef struct
|
||||
+{
|
||||
+ GSourceFunc source_func;
|
||||
+ gpointer user_data;
|
||||
+ GMutex mutex;
|
||||
+ GCond cond;
|
||||
+ gboolean completed;
|
||||
+} ContextInvokeData;
|
||||
+
|
||||
+static gboolean
|
||||
+source_func_wrapper (gpointer user_data)
|
||||
+{
|
||||
+ ContextInvokeData *data = user_data;
|
||||
+
|
||||
+ g_mutex_lock (&data->mutex);
|
||||
+
|
||||
+ while (data->source_func (data->user_data));
|
||||
+ data->completed = TRUE;
|
||||
+
|
||||
+ g_cond_signal (&data->cond);
|
||||
+ g_mutex_unlock (&data->mutex);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+trash_backend_worker_thread_queue_and_wait (GVfsBackendTrash *backend,
|
||||
+ GSourceFunc source_func)
|
||||
+{
|
||||
+ ContextInvokeData data;
|
||||
+
|
||||
+ data.source_func = source_func;
|
||||
+ data.user_data = backend;
|
||||
+
|
||||
+ g_mutex_init (&data.mutex);
|
||||
+ g_cond_init (&data.cond);
|
||||
+ data.completed = FALSE;
|
||||
+
|
||||
+ g_mutex_lock (&data.mutex);
|
||||
+
|
||||
+ g_main_context_invoke (backend->worker_context,
|
||||
+ source_func_wrapper,
|
||||
+ &data);
|
||||
+
|
||||
+ while (!data.completed)
|
||||
+ {
|
||||
+ g_cond_wait (&data.cond, &data.mutex);
|
||||
+ }
|
||||
+
|
||||
+ g_mutex_unlock (&data.mutex);
|
||||
+
|
||||
+ g_mutex_clear (&data.mutex);
|
||||
+ g_cond_clear (&data.cond);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+trash_backend_worker_thread_queue (GVfsBackendTrash *backend,
|
||||
+ GSourceFunc source_func)
|
||||
+{
|
||||
+ g_main_context_invoke (backend->worker_context, source_func, backend);
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+watch_func (gpointer user_data)
|
||||
+{
|
||||
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (user_data);
|
||||
+
|
||||
+ trash_watcher_watch (backend->watcher);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+rescan_func (gpointer user_data)
|
||||
+{
|
||||
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (user_data);
|
||||
+
|
||||
+ trash_watcher_rescan (backend->watcher);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+ready_func (gpointer user_data)
|
||||
+{
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
is_root (const char *filename)
|
||||
{
|
||||
@@ -63,7 +155,7 @@ trash_backend_get_file_monitor (GVfsBackendTrash *backend,
|
||||
* no possibility here for creating more than one new monitor.
|
||||
*/
|
||||
if (backend->dir_monitor == NULL)
|
||||
- trash_watcher_watch (backend->watcher);
|
||||
+ trash_backend_worker_thread_queue (backend, watch_func);
|
||||
|
||||
backend->file_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
}
|
||||
@@ -84,7 +176,7 @@ trash_backend_get_dir_monitor (GVfsBackendTrash *backend,
|
||||
* no possibility here for creating more than one new monitor.
|
||||
*/
|
||||
if (backend->file_monitor == NULL)
|
||||
- trash_watcher_watch (backend->watcher);
|
||||
+ trash_backend_worker_thread_queue (backend, watch_func);
|
||||
|
||||
backend->dir_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
}
|
||||
@@ -164,7 +256,6 @@ trash_backend_item_count_changed (gpointer user_data)
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
static GFile *
|
||||
trash_backend_get_file (GVfsBackendTrash *backend,
|
||||
const char *filename,
|
||||
@@ -177,6 +268,8 @@ trash_backend_get_file (GVfsBackendTrash *backend,
|
||||
TrashItem *item;
|
||||
GFile *file;
|
||||
|
||||
+ trash_backend_worker_thread_queue_and_wait (backend, rescan_func);
|
||||
+
|
||||
file = NULL;
|
||||
filename++;
|
||||
|
||||
@@ -243,9 +336,6 @@ trash_backend_open_for_read (GVfsBackend *vfs_backend,
|
||||
{
|
||||
GFile *real;
|
||||
|
||||
- if (!backend->file_monitor && !backend->dir_monitor)
|
||||
- trash_watcher_rescan (backend->watcher);
|
||||
-
|
||||
real = trash_backend_get_file (backend, filename, NULL, NULL, &error);
|
||||
|
||||
if (real)
|
||||
@@ -404,9 +494,6 @@ trash_backend_delete (GVfsBackend *vfs_backend,
|
||||
TrashItem *item;
|
||||
GFile *real;
|
||||
|
||||
- if (!backend->file_monitor && !backend->dir_monitor)
|
||||
- trash_watcher_rescan (backend->watcher);
|
||||
-
|
||||
real = trash_backend_get_file (backend, filename,
|
||||
&item, &is_toplevel, &error);
|
||||
|
||||
@@ -461,9 +548,6 @@ trash_backend_pull (GVfsBackend *vfs_backend,
|
||||
TrashItem *item;
|
||||
GFile *real;
|
||||
|
||||
- if (!backend->file_monitor && !backend->dir_monitor)
|
||||
- trash_watcher_rescan (backend->watcher);
|
||||
-
|
||||
real = trash_backend_get_file (backend, source, &item,
|
||||
&is_toplevel, &error);
|
||||
|
||||
@@ -585,6 +669,8 @@ trash_backend_enumerate_root (GVfsBackendTrash *backend,
|
||||
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
|
||||
+ trash_backend_worker_thread_queue_and_wait (backend, rescan_func);
|
||||
+
|
||||
items = trash_root_get_items (backend->root);
|
||||
|
||||
for (node = items; node; node = node->next)
|
||||
@@ -675,8 +761,6 @@ trash_backend_enumerate (GVfsBackend *vfs_backend,
|
||||
|
||||
g_assert (filename[0] == '/');
|
||||
|
||||
- trash_watcher_rescan (backend->watcher);
|
||||
-
|
||||
if (!is_root (filename))
|
||||
trash_backend_enumerate_non_root (backend, job, filename,
|
||||
attribute_matcher, flags);
|
||||
@@ -684,6 +768,31 @@ trash_backend_enumerate (GVfsBackend *vfs_backend,
|
||||
trash_backend_enumerate_root (backend, job, attribute_matcher, flags);
|
||||
}
|
||||
|
||||
+static gpointer
|
||||
+thread_func (gpointer user_data)
|
||||
+{
|
||||
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (user_data);
|
||||
+
|
||||
+ g_main_context_push_thread_default (backend->worker_context);
|
||||
+ backend->worker_loop = g_main_loop_new (backend->worker_context, FALSE);
|
||||
+
|
||||
+ backend->root = trash_root_new (trash_backend_item_created,
|
||||
+ trash_backend_item_deleted,
|
||||
+ trash_backend_item_count_changed,
|
||||
+ backend);
|
||||
+ backend->watcher = trash_watcher_new (backend->root);
|
||||
+
|
||||
+ g_main_loop_run (backend->worker_loop);
|
||||
+
|
||||
+ trash_watcher_free (backend->watcher);
|
||||
+ trash_root_free (backend->root);
|
||||
+
|
||||
+ g_main_context_pop_thread_default (backend->worker_context);
|
||||
+ g_main_loop_unref (backend->worker_loop);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
trash_backend_mount (GVfsBackend *vfs_backend,
|
||||
GVfsJobMount *job,
|
||||
@@ -695,11 +804,12 @@ trash_backend_mount (GVfsBackend *vfs_backend,
|
||||
|
||||
backend->file_monitor = NULL;
|
||||
backend->dir_monitor = NULL;
|
||||
- backend->root = trash_root_new (trash_backend_item_created,
|
||||
- trash_backend_item_deleted,
|
||||
- trash_backend_item_count_changed,
|
||||
- backend);
|
||||
- backend->watcher = trash_watcher_new (backend->root);
|
||||
+
|
||||
+ backend->worker_context = g_main_context_new ();
|
||||
+ backend->worker_thread = g_thread_new ("Trash Worker Thread",
|
||||
+ thread_func,
|
||||
+ backend);
|
||||
+ trash_backend_worker_thread_queue_and_wait (backend, ready_func);
|
||||
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
}
|
||||
@@ -716,9 +826,6 @@ trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
|
||||
g_assert (filename[0] == '/');
|
||||
|
||||
- if (!backend->file_monitor && !backend->dir_monitor)
|
||||
- trash_watcher_rescan (backend->watcher);
|
||||
-
|
||||
if (!is_root (filename))
|
||||
{
|
||||
GError *error = NULL;
|
||||
@@ -762,6 +869,8 @@ trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
GIcon *icon;
|
||||
int n_items;
|
||||
|
||||
+ trash_backend_worker_thread_queue_and_wait (backend, rescan_func);
|
||||
+
|
||||
n_items = trash_root_get_n_items (backend->root);
|
||||
|
||||
g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
|
||||
@@ -878,9 +987,6 @@ trash_backend_finalize (GObject *object)
|
||||
if (backend->dir_monitor)
|
||||
g_object_unref (backend->dir_monitor);
|
||||
backend->dir_monitor = NULL;
|
||||
-
|
||||
- trash_watcher_free (backend->watcher);
|
||||
- trash_root_free (backend->root);
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
From f1cdb812f8fa6f06239183923f920025a05e0712 Mon Sep 17 00:00:00 2001
|
||||
From: Maximiliano Sandoval <msandova@gnome.org>
|
||||
Date: Fri, 10 Apr 2026 23:52:16 +0200
|
||||
Subject: [PATCH] trash: Chain up finalize
|
||||
|
||||
Currently, `trash_backend_finalize()` only releases backend-specific
|
||||
monitors. Without chaining up, parent `GObject` finalization is
|
||||
skipped, which can leave parent-side teardown incomplete. Let's call
|
||||
`g_vfs_backend_trash_parent_class->finalize()` at the end of
|
||||
`trash_backned_finalize()`.
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index 0966242a..1dcb44f0 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -987,6 +987,8 @@ trash_backend_finalize (GObject *object)
|
||||
if (backend->dir_monitor)
|
||||
g_object_unref (backend->dir_monitor);
|
||||
backend->dir_monitor = NULL;
|
||||
+
|
||||
+ G_OBJECT_CLASS (g_vfs_backend_trash_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
From 5e34cc212b32e58fd7b6721d92548e983fecd991 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 2 Jun 2026 15:54:33 +0200
|
||||
Subject: [PATCH] trash: Defer mount monitoring to active watchers only
|
||||
|
||||
Backport of commit b53d45db.
|
||||
|
||||
Adjusted context for target version.
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 26 +++++++++++++++++++++-----
|
||||
1 file changed, 21 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index bd658e1..3a1bc9f 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -139,6 +139,7 @@ struct OPAQUE_TYPE__TrashWatcher
|
||||
TrashRoot *root;
|
||||
|
||||
GUnixMountMonitor *mount_monitor;
|
||||
+ gulong mounts_changed_id;
|
||||
GHashTable *mounts; /* mount_path -> TrashMount */
|
||||
guint update_id;
|
||||
|
||||
@@ -339,8 +340,7 @@ trash_watcher_new (TrashRoot *root)
|
||||
watcher->watching = FALSE;
|
||||
watcher->update_id = 0;
|
||||
watcher->mount_monitor = g_unix_mount_monitor_get ();
|
||||
- g_signal_connect_swapped (watcher->mount_monitor, "mounts_changed",
|
||||
- G_CALLBACK (trash_watcher_remount), watcher);
|
||||
+ watcher->mounts_changed_id = 0;
|
||||
|
||||
user_datadir = g_file_new_for_path (g_get_user_data_dir ());
|
||||
homedir_trashdir = g_file_get_child (user_datadir, "Trash/files");
|
||||
@@ -378,9 +378,17 @@ trash_watcher_watch (TrashWatcher *watcher)
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
+ g_debug ("trash_watcher_watch\n");
|
||||
+
|
||||
if (watcher->watching)
|
||||
return;
|
||||
|
||||
+ watcher->mounts_changed_id =
|
||||
+ g_signal_connect_swapped (watcher->mount_monitor, "mounts_changed",
|
||||
+ G_CALLBACK (trash_watcher_remount), watcher);
|
||||
+
|
||||
+ trash_watcher_remount_do (watcher);
|
||||
+
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_watch (watcher->homedir_trashdir);
|
||||
|
||||
@@ -404,9 +412,17 @@ trash_watcher_unwatch (TrashWatcher *watcher)
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
+ g_debug ("trash_watcher_unwatch\n");
|
||||
+
|
||||
if (!watcher->watching)
|
||||
return;
|
||||
|
||||
+ g_signal_handler_disconnect (watcher->mount_monitor,
|
||||
+ watcher->mounts_changed_id);
|
||||
+ watcher->mounts_changed_id = 0;
|
||||
+
|
||||
+ g_clear_handle_id (&watcher->update_id, g_source_remove);
|
||||
+
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_unwatch (watcher->homedir_trashdir);
|
||||
|
||||
@@ -430,7 +446,9 @@ trash_watcher_rescan (TrashWatcher *watcher)
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
- if (watcher->update_id != 0)
|
||||
+ if (!watcher->watching)
|
||||
+ trash_watcher_remount_do (watcher);
|
||||
+ else if (watcher->update_id != 0)
|
||||
{
|
||||
g_source_remove (watcher->update_id);
|
||||
trash_watcher_remount_timeout (watcher);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
From 85a789c800ef2773af6eb8884fef746d67d3cafe Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Fri, 20 Jan 2023 09:17:00 +0100
|
||||
Subject: [PATCH] trash: Do not create monitors for non-root items
|
||||
|
||||
The `create_dir_monitor` and `create_file_monitor` methods never fail
|
||||
currently. However, no events are emitted for non-root items. Let's
|
||||
return the `G_IO_ERROR_NOT_SUPPORTED` error for non-root items instead.
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 22 ++++++++++++++++------
|
||||
1 file changed, 16 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index d7ec4f77..76c9e006 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -839,10 +839,15 @@ trash_backend_create_dir_monitor (GVfsBackend *vfs_backend,
|
||||
GVfsMonitor *monitor;
|
||||
|
||||
if (!is_root (filename))
|
||||
- monitor = g_vfs_monitor_new (vfs_backend);
|
||||
- else
|
||||
- monitor = trash_backend_get_dir_monitor (backend, TRUE);
|
||||
+ {
|
||||
+ g_vfs_job_failed (G_VFS_JOB (job),
|
||||
+ G_IO_ERROR,
|
||||
+ G_IO_ERROR_NOT_SUPPORTED,
|
||||
+ _("Operation not supported"));
|
||||
+ return TRUE;
|
||||
+ }
|
||||
|
||||
+ monitor = trash_backend_get_dir_monitor (backend, TRUE);
|
||||
g_vfs_job_create_monitor_set_monitor (job, monitor);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
g_object_unref (monitor);
|
||||
@@ -860,10 +865,15 @@ trash_backend_create_file_monitor (GVfsBackend *vfs_backend,
|
||||
GVfsMonitor *monitor;
|
||||
|
||||
if (!is_root (filename))
|
||||
- monitor = g_vfs_monitor_new (vfs_backend);
|
||||
- else
|
||||
- monitor = trash_backend_get_file_monitor (backend, TRUE);
|
||||
+ {
|
||||
+ g_vfs_job_failed (G_VFS_JOB (job),
|
||||
+ G_IO_ERROR,
|
||||
+ G_IO_ERROR_NOT_SUPPORTED,
|
||||
+ _("Operation not supported"));
|
||||
+ return TRUE;
|
||||
+ }
|
||||
|
||||
+ monitor = trash_backend_get_file_monitor (backend, TRUE);
|
||||
g_vfs_job_create_monitor_set_monitor (job, monitor);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
g_object_unref (monitor);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
From 181da9f0d10a9e75795db5bb138214a89382271f Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Fri, 21 Nov 2025 13:28:55 +0100
|
||||
Subject: [PATCH] trash: Rate limit mount updates
|
||||
|
||||
Currently, the trash daemon processes every `mounts_changed` signal.
|
||||
This leads to high CPU usage when many mount events occur in a short
|
||||
timeframe. Let's rate limit mount processing to avoid high CPU usage
|
||||
in this case. The timeout is randomly chosen within the interval
|
||||
50-500 ms to better balance the load when multiple daemons are
|
||||
running simultaneously.
|
||||
|
||||
Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/814
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 39 ++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 37 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index 80a24d3d..664380c6 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -142,6 +142,7 @@ struct OPAQUE_TYPE__TrashWatcher
|
||||
|
||||
GUnixMountMonitor *mount_monitor;
|
||||
TrashMount *mounts;
|
||||
+ guint update_id;
|
||||
|
||||
TrashDir *homedir_trashdir;
|
||||
WatchType homedir_type;
|
||||
@@ -158,6 +159,8 @@ struct _TrashMount
|
||||
TrashMount *next;
|
||||
};
|
||||
|
||||
+#define UPDATE_TIMEOUT 100 /* ms */
|
||||
+
|
||||
static void
|
||||
trash_mount_insert (TrashWatcher *watcher,
|
||||
TrashMount ***mount_ptr_ptr,
|
||||
@@ -247,7 +250,7 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
}
|
||||
|
||||
static void
|
||||
-trash_watcher_remount (TrashWatcher *watcher)
|
||||
+trash_watcher_remount_do (TrashWatcher *watcher)
|
||||
{
|
||||
TrashMount **old;
|
||||
GList *mounts;
|
||||
@@ -298,6 +301,29 @@ trash_watcher_remount (TrashWatcher *watcher)
|
||||
g_list_free (mounts);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+trash_watcher_remount_timeout (gpointer user_data)
|
||||
+{
|
||||
+ TrashWatcher *watcher = user_data;
|
||||
+
|
||||
+ watcher->update_id = 0;
|
||||
+
|
||||
+ trash_watcher_remount_do (watcher);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+trash_watcher_remount (TrashWatcher *watcher)
|
||||
+{
|
||||
+ if (watcher->update_id != 0)
|
||||
+ return;
|
||||
+
|
||||
+ watcher->update_id = g_timeout_add (UPDATE_TIMEOUT * g_random_double_range (0.5, 5),
|
||||
+ trash_watcher_remount_timeout,
|
||||
+ watcher);
|
||||
+}
|
||||
+
|
||||
TrashWatcher *
|
||||
trash_watcher_new (TrashRoot *root)
|
||||
{
|
||||
@@ -310,6 +336,7 @@ trash_watcher_new (TrashRoot *root)
|
||||
watcher->root = root;
|
||||
watcher->mounts = NULL;
|
||||
watcher->watching = FALSE;
|
||||
+ watcher->update_id = 0;
|
||||
watcher->mount_monitor = g_unix_mount_monitor_get ();
|
||||
g_signal_connect_swapped (watcher->mount_monitor, "mounts_changed",
|
||||
G_CALLBACK (trash_watcher_remount), watcher);
|
||||
@@ -328,7 +355,7 @@ trash_watcher_new (TrashRoot *root)
|
||||
g_object_unref (homedir_trashdir);
|
||||
g_object_unref (user_datadir);
|
||||
|
||||
- trash_watcher_remount (watcher);
|
||||
+ trash_watcher_remount_do (watcher);
|
||||
|
||||
return watcher;
|
||||
}
|
||||
@@ -336,6 +363,8 @@ trash_watcher_new (TrashRoot *root)
|
||||
void
|
||||
trash_watcher_free (TrashWatcher *watcher)
|
||||
{
|
||||
+ g_clear_handle_id (&watcher->update_id, g_source_remove);
|
||||
+
|
||||
/* We just leak everything here, as this is not normally hit.
|
||||
This used to be a g_assert_not_reached(), and that got hit when
|
||||
mounting the trash backend failed due to the trash already being
|
||||
@@ -387,6 +416,12 @@ trash_watcher_rescan (TrashWatcher *watcher)
|
||||
{
|
||||
TrashMount *mount;
|
||||
|
||||
+ if (watcher->update_id != 0)
|
||||
+ {
|
||||
+ g_source_remove (watcher->update_id);
|
||||
+ trash_watcher_remount_timeout (watcher);
|
||||
+ }
|
||||
+
|
||||
if (!watcher->watching || watcher->homedir_type != TRASH_WATCHER_TRUSTED)
|
||||
trash_dir_rescan (watcher->homedir_trashdir);
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
From 68a056dd3764c795c5d9d5844e2cc3f20f9eaf1d Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 3 Feb 2026 16:47:50 +0100
|
||||
Subject: [PATCH] trash: Rate limit size change notifications
|
||||
|
||||
Currently, the `attribute-changed` signal is emitted after every file
|
||||
change. This can lead to higher CPU usage if too many changes occur
|
||||
in a short time frame. To avoid this, let's limit the frequency of the
|
||||
signal to a maximum of 100 ms.
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
|
||||
Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/814
|
||||
---
|
||||
daemon/trashlib/trashitem.c | 26 +++++++++++++++++++++++---
|
||||
1 file changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashitem.c b/daemon/trashlib/trashitem.c
|
||||
index a5b5b166..08dd8ad8 100644
|
||||
--- a/daemon/trashlib/trashitem.c
|
||||
+++ b/daemon/trashlib/trashitem.c
|
||||
@@ -30,8 +30,12 @@ struct OPAQUE_TYPE__TrashRoot
|
||||
|
||||
GHashTable *item_table;
|
||||
int old_size;
|
||||
+
|
||||
+ guint size_change_id;
|
||||
};
|
||||
|
||||
+#define SIZE_CHANGE_TIMEOUT 100 /* ms */
|
||||
+
|
||||
struct OPAQUE_TYPE__TrashItem
|
||||
{
|
||||
TrashRoot *root;
|
||||
@@ -283,6 +287,17 @@ trash_item_invoke_closure (NotifyClosure *closure)
|
||||
g_slice_free (NotifyClosure, closure);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+trash_root_size_change_timeout (gpointer user_data)
|
||||
+{
|
||||
+ TrashRoot *root = user_data;
|
||||
+
|
||||
+ root->size_change_id = 0;
|
||||
+ root->size_change (root->user_data);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
void
|
||||
trash_root_thaw (TrashRoot *root)
|
||||
{
|
||||
@@ -308,10 +323,13 @@ trash_root_thaw (TrashRoot *root)
|
||||
size_changed = root->old_size != size;
|
||||
root->old_size = size;
|
||||
|
||||
- g_rw_lock_writer_unlock (&root->lock);
|
||||
+ /* Rate limit size_change notifications */
|
||||
+ if (size_changed && root->size_change_id == 0)
|
||||
+ root->size_change_id = g_timeout_add (SIZE_CHANGE_TIMEOUT,
|
||||
+ trash_root_size_change_timeout,
|
||||
+ root);
|
||||
|
||||
- if (size_changed)
|
||||
- root->size_change (root->user_data);
|
||||
+ g_rw_lock_writer_unlock (&root->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -341,6 +359,7 @@ trash_root_new (trash_item_notify create,
|
||||
root->item_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL, trash_item_removed);
|
||||
root->old_size = 0;
|
||||
+ root->size_change_id = 0;
|
||||
|
||||
return root;
|
||||
}
|
||||
@@ -348,6 +367,7 @@ trash_root_new (trash_item_notify create,
|
||||
void
|
||||
trash_root_free (TrashRoot *root)
|
||||
{
|
||||
+ g_clear_handle_id (&root->size_change_id, g_source_remove);
|
||||
g_hash_table_destroy (root->item_table);
|
||||
|
||||
while (!g_queue_is_empty (root->notifications))
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
From f8504e445976830287dcb44a51514dc4c15fe528 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 7 Jun 2023 15:50:51 +0200
|
||||
Subject: [PATCH] trash: Remove unused is_homedir property
|
||||
|
||||
---
|
||||
daemon/trashlib/trashitem.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashitem.c b/daemon/trashlib/trashitem.c
|
||||
index 08912856..a5b5b166 100644
|
||||
--- a/daemon/trashlib/trashitem.c
|
||||
+++ b/daemon/trashlib/trashitem.c
|
||||
@@ -29,7 +29,6 @@ struct OPAQUE_TYPE__TrashRoot
|
||||
gpointer user_data;
|
||||
|
||||
GHashTable *item_table;
|
||||
- gboolean is_homedir;
|
||||
int old_size;
|
||||
};
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
From 07f55a1dae9af0852fed9d774a6ab7d5a924d5e1 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Fri, 20 Jan 2023 15:43:10 +0100
|
||||
Subject: [PATCH] trash: Remove unused ui_hook property
|
||||
|
||||
---
|
||||
daemon/trashlib/trashdir.c | 11 -----------
|
||||
daemon/trashlib/trashdir.h | 5 -----
|
||||
2 files changed, 16 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashdir.c b/daemon/trashlib/trashdir.c
|
||||
index 0d7d2b1b..707dff6c 100644
|
||||
--- a/daemon/trashlib/trashdir.c
|
||||
+++ b/daemon/trashlib/trashdir.c
|
||||
@@ -373,8 +373,6 @@ trash_dir_rescan (TrashDir *dir)
|
||||
trash_dir_empty (dir);
|
||||
}
|
||||
|
||||
-static trash_dir_ui_hook ui_hook;
|
||||
-
|
||||
TrashDir *
|
||||
trash_dir_new (TrashRoot *root,
|
||||
gboolean watching,
|
||||
@@ -411,20 +409,11 @@ trash_dir_new (TrashRoot *root,
|
||||
else
|
||||
dir->watch = NULL;
|
||||
|
||||
- if (ui_hook)
|
||||
- ui_hook (dir, dir->directory);
|
||||
-
|
||||
g_free (rel);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
-void
|
||||
-trash_dir_set_ui_hook (trash_dir_ui_hook _ui_hook)
|
||||
-{
|
||||
- ui_hook = _ui_hook;
|
||||
-}
|
||||
-
|
||||
void
|
||||
trash_dir_free (TrashDir *dir)
|
||||
{
|
||||
diff --git a/daemon/trashlib/trashdir.h b/daemon/trashlib/trashdir.h
|
||||
index 5612f9ba..4c39d516 100644
|
||||
--- a/daemon/trashlib/trashdir.h
|
||||
+++ b/daemon/trashlib/trashdir.h
|
||||
@@ -15,9 +15,6 @@
|
||||
|
||||
typedef struct OPAQUE_TYPE__TrashDir TrashDir;
|
||||
|
||||
-typedef void (*trash_dir_ui_hook) (TrashDir *dir,
|
||||
- GFile *directory);
|
||||
-
|
||||
TrashDir *trash_dir_new (TrashRoot *root,
|
||||
gboolean watching,
|
||||
gboolean is_homedir,
|
||||
@@ -31,6 +28,4 @@ void trash_dir_watch (TrashDir *dir);
|
||||
void trash_dir_unwatch (TrashDir *dir);
|
||||
void trash_dir_rescan (TrashDir *dir);
|
||||
|
||||
-void trash_dir_set_ui_hook (trash_dir_ui_hook ui_hook);
|
||||
-
|
||||
#endif /* _trashdir_h_ */
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,241 +0,0 @@
|
||||
From 3889e4dec938a8023b8120545d4b53083b209dab Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Thu, 19 Jan 2023 12:12:52 +0100
|
||||
Subject: [PATCH] trash: Run blocking methods on a thread pool
|
||||
|
||||
All jobs use `_try` methods currently. This is wrong as most of them can
|
||||
block. This works quite ok except the case of stale NFS mounts that can
|
||||
block the main loop forever. Let's run the jobs on a thread pool instead.
|
||||
This reverts commit 01fe5a61 except for the `create_dir_monitor` and
|
||||
`create_file_monitor` methods in order to avoid issues like
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=723305.
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 68 ++++++++++++++-------------------------
|
||||
1 file changed, 25 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index 76c9e006..b4d3d089 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -227,7 +227,7 @@ trash_backend_get_file (GVfsBackendTrash *backend,
|
||||
}
|
||||
|
||||
/* ======================= method implementations ======================= */
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_open_for_read (GVfsBackend *vfs_backend,
|
||||
GVfsJobOpenForRead *job,
|
||||
const char *filename)
|
||||
@@ -261,18 +261,16 @@ trash_backend_open_for_read (GVfsBackend *vfs_backend,
|
||||
g_vfs_job_open_for_read_set_can_seek (job, TRUE);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_read (GVfsBackend *backend,
|
||||
GVfsJobRead *job,
|
||||
GVfsBackendHandle handle,
|
||||
@@ -290,16 +288,14 @@ trash_backend_read (GVfsBackend *backend,
|
||||
g_vfs_job_read_set_size (job, bytes);
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_seek_on_read (GVfsBackend *backend,
|
||||
GVfsJobSeekRead *job,
|
||||
GVfsBackendHandle handle,
|
||||
@@ -313,13 +309,11 @@ trash_backend_seek_on_read (GVfsBackend *backend,
|
||||
g_vfs_job_seek_read_set_offset (job, g_seekable_tell (handle));
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -349,7 +343,7 @@ trash_backend_query_info_on_read (GVfsBackend *backend,
|
||||
}
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_close_read (GVfsBackend *backend,
|
||||
GVfsJobCloseRead *job,
|
||||
GVfsBackendHandle handle)
|
||||
@@ -361,15 +355,13 @@ trash_backend_close_read (GVfsBackend *backend,
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
g_object_unref (handle);
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
|
||||
g_object_unref (handle);
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -394,7 +386,7 @@ trash_backend_schedule_thaw (GVfsBackendTrash *backend)
|
||||
backend);
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_delete (GVfsBackend *vfs_backend,
|
||||
GVfsJobDelete *job,
|
||||
const char *filename)
|
||||
@@ -435,7 +427,7 @@ trash_backend_delete (GVfsBackend *vfs_backend,
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
trash_item_unref (item);
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,11 +437,9 @@ trash_backend_delete (GVfsBackend *vfs_backend,
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_pull (GVfsBackend *vfs_backend,
|
||||
GVfsJobPull *job,
|
||||
const gchar *source,
|
||||
@@ -505,7 +495,7 @@ trash_backend_pull (GVfsBackend *vfs_backend,
|
||||
trash_item_unref (item);
|
||||
g_object_unref (real);
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,8 +507,6 @@ trash_backend_pull (GVfsBackend *vfs_backend,
|
||||
|
||||
g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
||||
g_error_free (error);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -676,7 +664,7 @@ trash_backend_enumerate_non_root (GVfsBackendTrash *backend,
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_enumerate (GVfsBackend *vfs_backend,
|
||||
GVfsJobEnumerate *job,
|
||||
const char *filename,
|
||||
@@ -694,11 +682,9 @@ trash_backend_enumerate (GVfsBackend *vfs_backend,
|
||||
attribute_matcher, flags);
|
||||
else
|
||||
trash_backend_enumerate_root (backend, job, attribute_matcher, flags);
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_mount (GVfsBackend *vfs_backend,
|
||||
GVfsJobMount *job,
|
||||
GMountSpec *mount_spec,
|
||||
@@ -716,11 +702,9 @@ trash_backend_mount (GVfsBackend *vfs_backend,
|
||||
backend->watcher = trash_watcher_new (backend->root);
|
||||
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
GVfsJobQueryInfo *job,
|
||||
const char *filename,
|
||||
@@ -764,7 +748,7 @@ trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
trash_item_unref (item);
|
||||
g_object_unref (real_info);
|
||||
|
||||
- return TRUE;
|
||||
+ return;
|
||||
}
|
||||
|
||||
trash_item_unref (item);
|
||||
@@ -798,8 +782,6 @@ trash_backend_query_info (GVfsBackend *vfs_backend,
|
||||
|
||||
g_vfs_job_succeeded (G_VFS_JOB (job));
|
||||
}
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -926,17 +908,17 @@ g_vfs_backend_trash_class_init (GVfsBackendTrashClass *class)
|
||||
|
||||
gobject_class->finalize = trash_backend_finalize;
|
||||
|
||||
- backend_class->try_mount = trash_backend_mount;
|
||||
- backend_class->try_open_for_read = trash_backend_open_for_read;
|
||||
- backend_class->try_read = trash_backend_read;
|
||||
- backend_class->try_seek_on_read = trash_backend_seek_on_read;
|
||||
+ backend_class->mount = trash_backend_mount;
|
||||
+ backend_class->open_for_read = trash_backend_open_for_read;
|
||||
+ backend_class->read = trash_backend_read;
|
||||
+ backend_class->seek_on_read = trash_backend_seek_on_read;
|
||||
backend_class->query_info_on_read = trash_backend_query_info_on_read;
|
||||
- backend_class->try_close_read = trash_backend_close_read;
|
||||
- backend_class->try_query_info = trash_backend_query_info;
|
||||
+ backend_class->close_read = trash_backend_close_read;
|
||||
+ backend_class->query_info = trash_backend_query_info;
|
||||
backend_class->try_query_fs_info = trash_backend_query_fs_info;
|
||||
- backend_class->try_enumerate = trash_backend_enumerate;
|
||||
- backend_class->try_delete = trash_backend_delete;
|
||||
- backend_class->try_pull = trash_backend_pull;
|
||||
+ backend_class->enumerate = trash_backend_enumerate;
|
||||
+ backend_class->delete = trash_backend_delete;
|
||||
+ backend_class->pull = trash_backend_pull;
|
||||
backend_class->try_create_dir_monitor = trash_backend_create_dir_monitor;
|
||||
backend_class->try_create_file_monitor = trash_backend_create_file_monitor;
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From 1ae1e68794a01b524d91c3da0addeca4d060b795 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 2 Jun 2026 15:54:37 +0200
|
||||
Subject: [PATCH] trash: Skip mount table reparsing when unchanged
|
||||
|
||||
Backport of commit e1821cdc.
|
||||
|
||||
Adapted for older GLib API: `g_unix_mount_entries_get`/`g_unix_mount_entries_changed_since` replaced with `g_unix_mounts_get`/`g_unix_mounts_changed_since`.
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index e44ab06..59303f0 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -142,6 +142,7 @@ struct OPAQUE_TYPE__TrashWatcher
|
||||
gulong mounts_changed_id;
|
||||
GHashTable *mounts; /* mount_path -> TrashMount */
|
||||
guint update_id;
|
||||
+ guint64 last_mount_time;
|
||||
|
||||
TrashDir *homedir_trashdir;
|
||||
WatchType homedir_type;
|
||||
@@ -246,7 +247,10 @@ trash_watcher_remount_do (TrashWatcher *watcher)
|
||||
gpointer key, value;
|
||||
const char *mount_path;
|
||||
|
||||
- mounts = g_unix_mounts_get (NULL);
|
||||
+ if (!g_unix_mounts_changed_since (watcher->last_mount_time))
|
||||
+ return;
|
||||
+
|
||||
+ mounts = g_unix_mounts_get (&watcher->last_mount_time);
|
||||
mount_paths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
for (l = mounts; l != NULL; l = l->next)
|
||||
@@ -339,6 +343,7 @@ trash_watcher_new (TrashRoot *root)
|
||||
watcher->mounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
watcher->watching = FALSE;
|
||||
watcher->update_id = 0;
|
||||
+ watcher->last_mount_time = 0;
|
||||
watcher->mount_monitor = g_unix_mount_monitor_get ();
|
||||
watcher->mounts_changed_id = 0;
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,280 +0,0 @@
|
||||
From 0f166b6f4f3e38144c779b3e6b55d777c6637b0e Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 3 Jun 2026 08:37:56 +0200
|
||||
Subject: [PATCH] trash: Use GHashTable for mount tracking
|
||||
|
||||
Backport of commit 64f8853f.
|
||||
|
||||
Adapted for older GLib API: `g_unix_mount_entry_*` replaced with `g_unix_mount_*`, `g_unix_mount_entries_get` replaced with `g_unix_mounts_get`.
|
||||
---
|
||||
daemon/trashlib/trashwatcher.c | 156 +++++++++++++++++----------------
|
||||
1 file changed, 80 insertions(+), 76 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index d8d6ef8..426f97f 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -139,7 +139,7 @@ struct OPAQUE_TYPE__TrashWatcher
|
||||
TrashRoot *root;
|
||||
|
||||
GUnixMountMonitor *mount_monitor;
|
||||
- TrashMount *mounts;
|
||||
+ GHashTable *mounts; /* mount_path -> TrashMount */
|
||||
guint update_id;
|
||||
|
||||
TrashDir *homedir_trashdir;
|
||||
@@ -153,16 +153,13 @@ struct _TrashMount
|
||||
GUnixMountEntry *mount_entry;
|
||||
TrashDir *dirs[2];
|
||||
WatchType type;
|
||||
-
|
||||
- TrashMount *next;
|
||||
};
|
||||
|
||||
#define UPDATE_TIMEOUT 100 /* ms */
|
||||
|
||||
static void
|
||||
-trash_mount_insert (TrashWatcher *watcher,
|
||||
- TrashMount ***mount_ptr_ptr,
|
||||
- GUnixMountEntry *mount_entry)
|
||||
+trash_mount_insert (TrashWatcher *watcher,
|
||||
+ GUnixMountEntry *mount_entry)
|
||||
{
|
||||
const char *mountpoint;
|
||||
gboolean watching;
|
||||
@@ -192,24 +189,15 @@ trash_mount_insert (TrashWatcher *watcher,
|
||||
mount->dirs[1] = trash_dir_new (watcher->root, watching, FALSE, mountpoint,
|
||||
".Trash-%d/files", (int) getuid ());
|
||||
|
||||
- mount->next = **mount_ptr_ptr;
|
||||
-
|
||||
- **mount_ptr_ptr = mount;
|
||||
- *mount_ptr_ptr = &mount->next;
|
||||
+ g_hash_table_insert (watcher->mounts, g_strdup (mountpoint), mount);
|
||||
}
|
||||
|
||||
static void
|
||||
-trash_mount_remove (TrashMount **mount_ptr)
|
||||
+trash_mount_free (TrashMount *mount)
|
||||
{
|
||||
- TrashMount *mount = *mount_ptr;
|
||||
-
|
||||
- /* first, the dirs */
|
||||
trash_dir_free (mount->dirs[0]);
|
||||
trash_dir_free (mount->dirs[1]);
|
||||
|
||||
- /* detach from list */
|
||||
- *mount_ptr = mount->next;
|
||||
-
|
||||
g_unix_mount_free (mount->mount_entry);
|
||||
g_slice_free (TrashMount, mount);
|
||||
}
|
||||
@@ -249,63 +237,64 @@ ignore_trash_mount (GUnixMountEntry *mount)
|
||||
static void
|
||||
trash_watcher_remount_do (TrashWatcher *watcher)
|
||||
{
|
||||
- TrashMount **old;
|
||||
+ GHashTable *mount_paths;
|
||||
+ GHashTableIter iter;
|
||||
GList *mounts;
|
||||
- GList *new;
|
||||
+ GList *l;
|
||||
+ gpointer key, value;
|
||||
+ const char *mount_path;
|
||||
|
||||
mounts = g_unix_mounts_get (NULL);
|
||||
- mounts = g_list_sort (mounts, (GCompareFunc) g_unix_mount_compare);
|
||||
+ mount_paths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
- old = &watcher->mounts;
|
||||
- new = mounts;
|
||||
-
|
||||
- /* synchronise the two lists */
|
||||
- while (*old || new)
|
||||
+ for (l = mounts; l != NULL; l = l->next)
|
||||
{
|
||||
- int result;
|
||||
+ g_autoptr(GUnixMountEntry) mount_entry = l->data;
|
||||
|
||||
- if (new && ignore_trash_mount (new->data))
|
||||
+ if (ignore_trash_mount (mount_entry))
|
||||
{
|
||||
- g_unix_mount_free (new->data);
|
||||
- new = new->next;
|
||||
+ g_debug ("trash_watcher_remount_do: ignore %s %s %s\n",
|
||||
+ g_unix_mount_get_device_path (mount_entry),
|
||||
+ g_unix_mount_get_mount_path (mount_entry),
|
||||
+ g_unix_mount_get_fs_type (mount_entry));
|
||||
continue;
|
||||
}
|
||||
|
||||
- if ((result = (new == NULL) - (*old == NULL)) == 0)
|
||||
- result = g_unix_mount_compare (new->data, (*old)->mount_entry);
|
||||
-
|
||||
- if (result < 0)
|
||||
+ mount_path = g_unix_mount_get_mount_path (mount_entry);
|
||||
+ if (!g_hash_table_contains (watcher->mounts, mount_path))
|
||||
{
|
||||
- /* new entry. add it. */
|
||||
g_debug ("trash_watcher_remount_do: insert %s %s %s\n",
|
||||
- g_unix_mount_get_device_path (new->data),
|
||||
- g_unix_mount_get_mount_path (new->data),
|
||||
- g_unix_mount_get_fs_type (new->data));
|
||||
+ g_unix_mount_get_device_path (mount_entry),
|
||||
+ g_unix_mount_get_mount_path (mount_entry),
|
||||
+ g_unix_mount_get_fs_type (mount_entry));
|
||||
|
||||
- trash_mount_insert (watcher, &old, new->data);
|
||||
- new = new->next;
|
||||
+ trash_mount_insert (watcher, g_steal_pointer (&mount_entry));
|
||||
}
|
||||
- else if (result > 0)
|
||||
- {
|
||||
- /* old entry. remove it. */
|
||||
- g_debug ("trash_watcher_remount_do: remove %s %s %s\n",
|
||||
- g_unix_mount_get_device_path ((*old)->mount_entry),
|
||||
- g_unix_mount_get_mount_path ((*old)->mount_entry),
|
||||
- g_unix_mount_get_fs_type ((*old)->mount_entry));
|
||||
|
||||
- trash_mount_remove (old);
|
||||
- }
|
||||
- else
|
||||
+ g_hash_table_add (mount_paths, g_strdup (mount_path));
|
||||
+ }
|
||||
+
|
||||
+ g_list_free (mounts);
|
||||
+
|
||||
+ g_hash_table_iter_init (&iter, watcher->mounts);
|
||||
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
+ {
|
||||
+ TrashMount *mount = value;
|
||||
+ mount_path = key;
|
||||
+
|
||||
+ if (!g_hash_table_contains (mount_paths, mount_path))
|
||||
{
|
||||
- /* match. no change. */
|
||||
- g_unix_mount_free (new->data);
|
||||
+ g_debug ("trash_watcher_remount_do: remove %s %s %s\n",
|
||||
+ g_unix_mount_get_device_path (mount->mount_entry),
|
||||
+ g_unix_mount_get_mount_path (mount->mount_entry),
|
||||
+ g_unix_mount_get_fs_type (mount->mount_entry));
|
||||
|
||||
- old = &(*old)->next;
|
||||
- new = new->next;
|
||||
+ trash_mount_free (mount);
|
||||
+ g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
- g_list_free (mounts);
|
||||
+ g_hash_table_destroy (mount_paths);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -345,7 +334,7 @@ trash_watcher_new (TrashRoot *root)
|
||||
|
||||
watcher = g_slice_new (TrashWatcher);
|
||||
watcher->root = root;
|
||||
- watcher->mounts = NULL;
|
||||
+ watcher->mounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
watcher->watching = FALSE;
|
||||
watcher->update_id = 0;
|
||||
watcher->mount_monitor = g_unix_mount_monitor_get ();
|
||||
@@ -385,19 +374,24 @@ trash_watcher_free (TrashWatcher *watcher)
|
||||
void
|
||||
trash_watcher_watch (TrashWatcher *watcher)
|
||||
{
|
||||
- TrashMount *mount;
|
||||
+ GHashTableIter iter;
|
||||
+ gpointer value;
|
||||
|
||||
g_assert (!watcher->watching);
|
||||
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_watch (watcher->homedir_trashdir);
|
||||
|
||||
- for (mount = watcher->mounts; mount; mount = mount->next)
|
||||
- if (mount->type != TRASH_WATCHER_NO_WATCH)
|
||||
- {
|
||||
- trash_dir_watch (mount->dirs[0]);
|
||||
- trash_dir_watch (mount->dirs[1]);
|
||||
- }
|
||||
+ g_hash_table_iter_init (&iter, watcher->mounts);
|
||||
+ while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
+ {
|
||||
+ TrashMount *mount = value;
|
||||
+ if (mount->type != TRASH_WATCHER_NO_WATCH)
|
||||
+ {
|
||||
+ trash_dir_watch (mount->dirs[0]);
|
||||
+ trash_dir_watch (mount->dirs[1]);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
watcher->watching = TRUE;
|
||||
}
|
||||
@@ -405,19 +399,24 @@ trash_watcher_watch (TrashWatcher *watcher)
|
||||
void
|
||||
trash_watcher_unwatch (TrashWatcher *watcher)
|
||||
{
|
||||
- TrashMount *mount;
|
||||
+ GHashTableIter iter;
|
||||
+ gpointer value;
|
||||
|
||||
g_assert (watcher->watching);
|
||||
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_unwatch (watcher->homedir_trashdir);
|
||||
|
||||
- for (mount = watcher->mounts; mount; mount = mount->next)
|
||||
- if (mount->type != TRASH_WATCHER_NO_WATCH)
|
||||
- {
|
||||
- trash_dir_unwatch (mount->dirs[0]);
|
||||
- trash_dir_unwatch (mount->dirs[1]);
|
||||
- }
|
||||
+ g_hash_table_iter_init (&iter, watcher->mounts);
|
||||
+ while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
+ {
|
||||
+ TrashMount *mount = value;
|
||||
+ if (mount->type != TRASH_WATCHER_NO_WATCH)
|
||||
+ {
|
||||
+ trash_dir_unwatch (mount->dirs[0]);
|
||||
+ trash_dir_unwatch (mount->dirs[1]);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
watcher->watching = FALSE;
|
||||
}
|
||||
@@ -425,7 +424,8 @@ trash_watcher_unwatch (TrashWatcher *watcher)
|
||||
void
|
||||
trash_watcher_rescan (TrashWatcher *watcher)
|
||||
{
|
||||
- TrashMount *mount;
|
||||
+ GHashTableIter iter;
|
||||
+ gpointer value;
|
||||
|
||||
if (watcher->update_id != 0)
|
||||
{
|
||||
@@ -436,10 +436,14 @@ trash_watcher_rescan (TrashWatcher *watcher)
|
||||
if (!watcher->watching || watcher->homedir_type != TRASH_WATCHER_TRUSTED)
|
||||
trash_dir_rescan (watcher->homedir_trashdir);
|
||||
|
||||
- for (mount = watcher->mounts; mount; mount = mount->next)
|
||||
- if (!watcher->watching || mount->type != TRASH_WATCHER_TRUSTED)
|
||||
- {
|
||||
- trash_dir_rescan (mount->dirs[0]);
|
||||
- trash_dir_rescan (mount->dirs[1]);
|
||||
- }
|
||||
+ g_hash_table_iter_init (&iter, watcher->mounts);
|
||||
+ while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
+ {
|
||||
+ TrashMount *mount = value;
|
||||
+ if (!watcher->watching || mount->type != TRASH_WATCHER_TRUSTED)
|
||||
+ {
|
||||
+ trash_dir_rescan (mount->dirs[0]);
|
||||
+ trash_dir_rescan (mount->dirs[1]);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -1,221 +0,0 @@
|
||||
From 97d9831042ca1c5c13fdb6cd9bfb2e2fe77f94f8 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Wed, 3 Jun 2026 08:45:00 +0200
|
||||
Subject: [PATCH] trash: Use GHashTable for trash directory items
|
||||
|
||||
Backport of commit 665ff6b8.
|
||||
|
||||
Adjusted context for target version.
|
||||
---
|
||||
daemon/trashlib/trashdir.c | 122 +++++++++++++++----------------------
|
||||
1 file changed, 48 insertions(+), 74 deletions(-)
|
||||
|
||||
diff --git a/daemon/trashlib/trashdir.c b/daemon/trashlib/trashdir.c
|
||||
index 23aa0d7..610f2c3 100644
|
||||
--- a/daemon/trashlib/trashdir.c
|
||||
+++ b/daemon/trashlib/trashdir.c
|
||||
@@ -16,7 +16,7 @@
|
||||
struct OPAQUE_TYPE__TrashDir
|
||||
{
|
||||
TrashRoot *root;
|
||||
- GSList *items;
|
||||
+ GHashTable *items; /* basename -> GFile */
|
||||
|
||||
GFile *directory;
|
||||
GFile *topdir;
|
||||
@@ -27,28 +27,6 @@ struct OPAQUE_TYPE__TrashDir
|
||||
GFileMonitor *monitor;
|
||||
};
|
||||
|
||||
-static gint
|
||||
-compare_basename (gconstpointer a,
|
||||
- gconstpointer b)
|
||||
-{
|
||||
- GFile *file_a, *file_b;
|
||||
- char *name_a, *name_b;
|
||||
- gint result;
|
||||
-
|
||||
- file_a = (GFile *) a;
|
||||
- file_b = (GFile *) b;
|
||||
-
|
||||
- name_a = g_file_get_basename (file_a);
|
||||
- name_b = g_file_get_basename (file_b);
|
||||
-
|
||||
- result = strcmp (name_a, name_b);
|
||||
-
|
||||
- g_free (name_a);
|
||||
- g_free (name_b);
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-
|
||||
static void
|
||||
trash_dir_query_mtime (TrashDir *dir, GTimeVal *mtime)
|
||||
{
|
||||
@@ -70,47 +48,36 @@ trash_dir_query_mtime (TrashDir *dir, GTimeVal *mtime)
|
||||
}
|
||||
|
||||
static void
|
||||
-trash_dir_set_files (TrashDir *dir,
|
||||
- GSList *items)
|
||||
+trash_dir_set_files (TrashDir *dir,
|
||||
+ GHashTable *items)
|
||||
{
|
||||
- GSList **old, *new;
|
||||
-
|
||||
- items = g_slist_sort (items, (GCompareFunc) compare_basename);
|
||||
- old = &dir->items;
|
||||
- new = items;
|
||||
+ GHashTableIter iter;
|
||||
+ gpointer key, value;
|
||||
|
||||
- while (new || *old)
|
||||
+ g_hash_table_iter_init (&iter, dir->items);
|
||||
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
- int result;
|
||||
-
|
||||
- if ((result = (new == NULL) - (*old == NULL)) == 0)
|
||||
- result = compare_basename (new->data, (*old)->data);
|
||||
-
|
||||
- if (result < 0)
|
||||
- {
|
||||
- /* new entry. add it. */
|
||||
- *old = g_slist_prepend (*old, new->data); /* take reference */
|
||||
- old = &(*old)->next;
|
||||
- trash_root_add_item (dir->root, new->data, dir->topdir, dir->is_homedir);
|
||||
- new = new->next;
|
||||
- }
|
||||
- else if (result > 0)
|
||||
+ if (!g_hash_table_contains (items, key))
|
||||
{
|
||||
/* old entry. remove it. */
|
||||
- trash_root_remove_item (dir->root, (*old)->data, dir->is_homedir);
|
||||
- g_object_unref ((*old)->data);
|
||||
- *old = g_slist_delete_link (*old, *old);
|
||||
+ trash_root_remove_item (dir->root, value, dir->is_homedir);
|
||||
+ g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
- else
|
||||
+ }
|
||||
+
|
||||
+ g_hash_table_iter_init (&iter, items);
|
||||
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
+ {
|
||||
+ if (!g_hash_table_contains (dir->items, key))
|
||||
{
|
||||
- /* match. no change. */
|
||||
- old = &(*old)->next;
|
||||
- g_object_unref (new->data);
|
||||
- new = new->next;
|
||||
+ /* new entry. add it. */
|
||||
+ g_hash_table_iter_steal (&iter);
|
||||
+ g_hash_table_insert (dir->items, key, value);
|
||||
+ trash_root_add_item (dir->root, value, dir->topdir, dir->is_homedir);
|
||||
}
|
||||
}
|
||||
|
||||
- g_slist_free (items);
|
||||
+ g_hash_table_unref (items);
|
||||
|
||||
trash_root_thaw (dir->root);
|
||||
}
|
||||
@@ -118,16 +85,23 @@ trash_dir_set_files (TrashDir *dir,
|
||||
static void
|
||||
trash_dir_empty (TrashDir *dir)
|
||||
{
|
||||
- trash_dir_set_files (dir, NULL);
|
||||
+ GHashTable *empty;
|
||||
+
|
||||
+ empty = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
+ trash_dir_set_files (dir, empty);
|
||||
}
|
||||
|
||||
static void
|
||||
trash_dir_enumerate (TrashDir *dir)
|
||||
{
|
||||
GFileEnumerator *enumerator;
|
||||
- GSList *files = NULL;
|
||||
+ GHashTable *files = NULL;
|
||||
|
||||
trash_dir_query_mtime (dir, &dir->mtime);
|
||||
+
|
||||
+ files = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
+ g_free, g_object_unref);
|
||||
+
|
||||
enumerator = g_file_enumerate_children (dir->directory,
|
||||
G_FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
@@ -140,10 +113,11 @@ trash_dir_enumerate (TrashDir *dir)
|
||||
while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
|
||||
{
|
||||
GFile *file;
|
||||
+ const gchar *name;
|
||||
|
||||
- file = g_file_get_child (dir->directory,
|
||||
- g_file_info_get_name (info));
|
||||
- files = g_slist_prepend (files, file);
|
||||
+ name = g_file_info_get_name (info);
|
||||
+ file = g_file_get_child (dir->directory, name);
|
||||
+ g_hash_table_insert (files, g_strdup (name), file);
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
@@ -165,24 +139,20 @@ trash_dir_changed (GFileMonitor *monitor,
|
||||
|
||||
if (event_type == G_FILE_MONITOR_EVENT_CREATED)
|
||||
{
|
||||
- dir->items = g_slist_insert_sorted (dir->items,
|
||||
- g_object_ref (file),
|
||||
- (GCompareFunc) compare_basename);
|
||||
- trash_root_add_item (dir->root, file, dir->topdir, dir->is_homedir);
|
||||
+ g_autofree gchar *name = g_file_get_basename (file);
|
||||
+
|
||||
+ if (!g_hash_table_contains (dir->items, name))
|
||||
+ {
|
||||
+ g_hash_table_insert (dir->items, g_steal_pointer (&name), g_object_ref (file));
|
||||
+ trash_root_add_item (dir->root, file, dir->topdir, dir->is_homedir);
|
||||
+ }
|
||||
}
|
||||
|
||||
else if (event_type == G_FILE_MONITOR_EVENT_DELETED)
|
||||
{
|
||||
- GSList *node;
|
||||
+ g_autofree char *name = g_file_get_basename (file);
|
||||
|
||||
- node = g_slist_find_custom (dir->items,
|
||||
- file,
|
||||
- (GCompareFunc) compare_basename);
|
||||
- if (node)
|
||||
- {
|
||||
- g_object_unref (node->data);
|
||||
- dir->items = g_slist_delete_link (dir->items, node);
|
||||
- }
|
||||
+ g_hash_table_remove (dir->items, name);
|
||||
trash_root_remove_item (dir->root, file, dir->is_homedir);
|
||||
}
|
||||
|
||||
@@ -386,7 +356,8 @@ trash_dir_new (TrashRoot *root,
|
||||
dir = g_slice_new (TrashDir);
|
||||
|
||||
dir->root = root;
|
||||
- dir->items = NULL;
|
||||
+ dir->items = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
+ g_free, g_object_unref);
|
||||
dir->topdir = g_file_new_for_path (mount_point);
|
||||
dir->directory = g_file_get_child (dir->topdir, rel);
|
||||
dir->monitor = NULL;
|
||||
@@ -416,7 +387,9 @@ trash_dir_free (TrashDir *dir)
|
||||
if (dir->monitor)
|
||||
g_object_unref (dir->monitor);
|
||||
|
||||
- trash_dir_set_files (dir, NULL);
|
||||
+ trash_dir_empty (dir);
|
||||
+
|
||||
+ g_hash_table_unref (dir->items);
|
||||
|
||||
g_object_unref (dir->directory);
|
||||
g_object_unref (dir->topdir);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,223 +0,0 @@
|
||||
From b15490d80dc8044dd546c8f5fba171bacb92c49c Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Holy <oholy@redhat.com>
|
||||
Date: Tue, 2 Jun 2026 15:54:17 +0200
|
||||
Subject: [PATCH] trash: Use weak refs for monitor lifecycle
|
||||
|
||||
Backport of commit 1080ca11.
|
||||
|
||||
Adjusted context for target version.
|
||||
---
|
||||
daemon/gvfsbackendtrash.c | 119 ++++++++++++++++++++++-----------
|
||||
daemon/trashlib/trashwatcher.c | 6 +-
|
||||
2 files changed, 84 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/daemon/gvfsbackendtrash.c b/daemon/gvfsbackendtrash.c
|
||||
index 1dcb44f..6d0af56 100644
|
||||
--- a/daemon/gvfsbackendtrash.c
|
||||
+++ b/daemon/gvfsbackendtrash.c
|
||||
@@ -33,8 +33,8 @@ struct OPAQUE_TYPE__GVfsBackendTrash
|
||||
{
|
||||
GVfsBackend parent_instance;
|
||||
|
||||
- GVfsMonitor *file_monitor;
|
||||
- GVfsMonitor *dir_monitor;
|
||||
+ GWeakRef file_monitor;
|
||||
+ GWeakRef dir_monitor;
|
||||
|
||||
GMainContext *worker_context;
|
||||
GMainLoop *worker_loop;
|
||||
@@ -111,15 +111,32 @@ trash_backend_worker_thread_queue (GVfsBackendTrash *backend,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
-watch_func (gpointer user_data)
|
||||
+sync_watch_state_func (gpointer user_data)
|
||||
{
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (user_data);
|
||||
+ GVfsMonitor *file_monitor;
|
||||
+ GVfsMonitor *dir_monitor;
|
||||
|
||||
- trash_watcher_watch (backend->watcher);
|
||||
+ file_monitor = g_weak_ref_get (&backend->file_monitor);
|
||||
+ dir_monitor = g_weak_ref_get (&backend->dir_monitor);
|
||||
+
|
||||
+ if (file_monitor != NULL || dir_monitor != NULL)
|
||||
+ trash_watcher_watch (backend->watcher);
|
||||
+ else
|
||||
+ trash_watcher_unwatch (backend->watcher);
|
||||
+
|
||||
+ g_clear_object (&file_monitor);
|
||||
+ g_clear_object (&dir_monitor);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
+static void
|
||||
+trash_backend_queue_watch_state_sync (GVfsBackendTrash *backend)
|
||||
+{
|
||||
+ trash_backend_worker_thread_queue (backend, sync_watch_state_func);
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
rescan_func (gpointer user_data)
|
||||
{
|
||||
@@ -142,46 +159,62 @@ is_root (const char *filename)
|
||||
return (filename[0] == '/' && filename[1] == '\0');
|
||||
}
|
||||
|
||||
+static void
|
||||
+trash_backend_file_monitor_destroyed (gpointer data,
|
||||
+ GObject *where_the_object_was)
|
||||
+{
|
||||
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (data);
|
||||
+
|
||||
+ trash_backend_queue_watch_state_sync (backend);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+trash_backend_dir_monitor_destroyed (gpointer data,
|
||||
+ GObject *where_the_object_was)
|
||||
+{
|
||||
+ GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (data);
|
||||
+
|
||||
+ trash_backend_queue_watch_state_sync (backend);
|
||||
+}
|
||||
+
|
||||
static GVfsMonitor *
|
||||
trash_backend_get_file_monitor (GVfsBackendTrash *backend,
|
||||
gboolean create)
|
||||
{
|
||||
- if (backend->file_monitor == NULL && create == FALSE)
|
||||
- return NULL;
|
||||
+ GVfsMonitor *monitor;
|
||||
|
||||
- else if (backend->file_monitor == NULL)
|
||||
- {
|
||||
- /* 'create' is only ever set in the main thread, so we will have
|
||||
- * no possibility here for creating more than one new monitor.
|
||||
- */
|
||||
- if (backend->dir_monitor == NULL)
|
||||
- trash_backend_worker_thread_queue (backend, watch_func);
|
||||
+ monitor = g_weak_ref_get (&backend->file_monitor);
|
||||
+ if (monitor != NULL || create == FALSE)
|
||||
+ return monitor;
|
||||
|
||||
- backend->file_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
- }
|
||||
+ monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
+ g_weak_ref_set (&backend->file_monitor, monitor);
|
||||
+ g_object_weak_ref (G_OBJECT (monitor),
|
||||
+ trash_backend_file_monitor_destroyed, backend);
|
||||
+
|
||||
+ trash_backend_queue_watch_state_sync (backend);
|
||||
|
||||
- return g_object_ref (backend->file_monitor);
|
||||
+ return monitor;
|
||||
}
|
||||
|
||||
static GVfsMonitor *
|
||||
trash_backend_get_dir_monitor (GVfsBackendTrash *backend,
|
||||
gboolean create)
|
||||
{
|
||||
- if (backend->dir_monitor == NULL && create == FALSE)
|
||||
- return NULL;
|
||||
+ GVfsMonitor *monitor;
|
||||
|
||||
- else if (backend->dir_monitor == NULL)
|
||||
- {
|
||||
- /* 'create' is only ever set in the main thread, so we will have
|
||||
- * no possibility here for creating more than one new monitor.
|
||||
- */
|
||||
- if (backend->file_monitor == NULL)
|
||||
- trash_backend_worker_thread_queue (backend, watch_func);
|
||||
+ monitor = g_weak_ref_get (&backend->dir_monitor);
|
||||
+ if (monitor != NULL || create == FALSE)
|
||||
+ return monitor;
|
||||
|
||||
- backend->dir_monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
- }
|
||||
+ monitor = g_vfs_monitor_new (G_VFS_BACKEND (backend));
|
||||
+ g_weak_ref_set (&backend->dir_monitor, monitor);
|
||||
+ g_object_weak_ref (G_OBJECT (monitor),
|
||||
+ trash_backend_dir_monitor_destroyed, backend);
|
||||
+
|
||||
+ trash_backend_queue_watch_state_sync (backend);
|
||||
|
||||
- return g_object_ref (backend->dir_monitor);
|
||||
+ return monitor;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -802,8 +835,8 @@ trash_backend_mount (GVfsBackend *vfs_backend,
|
||||
{
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend);
|
||||
|
||||
- backend->file_monitor = NULL;
|
||||
- backend->dir_monitor = NULL;
|
||||
+ g_weak_ref_init (&backend->file_monitor, NULL);
|
||||
+ g_weak_ref_init (&backend->dir_monitor, NULL);
|
||||
|
||||
backend->worker_context = g_main_context_new ();
|
||||
backend->worker_thread = g_thread_new ("Trash Worker Thread",
|
||||
@@ -976,17 +1009,25 @@ static void
|
||||
trash_backend_finalize (GObject *object)
|
||||
{
|
||||
GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (object);
|
||||
+ GVfsMonitor *monitor;
|
||||
|
||||
- /* get rid of these first to stop a flood of event notifications
|
||||
- * from being emitted while we're tearing down the TrashWatcher
|
||||
- */
|
||||
- if (backend->file_monitor)
|
||||
- g_object_unref (backend->file_monitor);
|
||||
- backend->file_monitor = NULL;
|
||||
+ monitor = g_weak_ref_get (&backend->file_monitor);
|
||||
+ if (monitor != NULL)
|
||||
+ {
|
||||
+ g_object_weak_unref (G_OBJECT (monitor),
|
||||
+ trash_backend_file_monitor_destroyed, backend);
|
||||
+ g_object_unref (monitor);
|
||||
+ }
|
||||
+ g_weak_ref_clear (&backend->file_monitor);
|
||||
|
||||
- if (backend->dir_monitor)
|
||||
- g_object_unref (backend->dir_monitor);
|
||||
- backend->dir_monitor = NULL;
|
||||
+ monitor = g_weak_ref_get (&backend->dir_monitor);
|
||||
+ if (monitor != NULL)
|
||||
+ {
|
||||
+ g_object_weak_unref (G_OBJECT (monitor),
|
||||
+ trash_backend_dir_monitor_destroyed, backend);
|
||||
+ g_object_unref (monitor);
|
||||
+ }
|
||||
+ g_weak_ref_clear (&backend->dir_monitor);
|
||||
|
||||
G_OBJECT_CLASS (g_vfs_backend_trash_parent_class)->finalize (object);
|
||||
}
|
||||
diff --git a/daemon/trashlib/trashwatcher.c b/daemon/trashlib/trashwatcher.c
|
||||
index 1888bed..bd658e1 100644
|
||||
--- a/daemon/trashlib/trashwatcher.c
|
||||
+++ b/daemon/trashlib/trashwatcher.c
|
||||
@@ -378,7 +378,8 @@ trash_watcher_watch (TrashWatcher *watcher)
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
- g_assert (!watcher->watching);
|
||||
+ if (watcher->watching)
|
||||
+ return;
|
||||
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_watch (watcher->homedir_trashdir);
|
||||
@@ -403,7 +404,8 @@ trash_watcher_unwatch (TrashWatcher *watcher)
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
- g_assert (watcher->watching);
|
||||
+ if (!watcher->watching)
|
||||
+ return;
|
||||
|
||||
if (watcher->homedir_type != TRASH_WATCHER_NO_WATCH)
|
||||
trash_dir_unwatch (watcher->homedir_trashdir);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
From 14dc69defb82a789999ba43e5350438d9c7086a6 Mon Sep 17 00:00:00 2001
|
||||
Date: Mon, 11 Mar 2024 10:20:51 +0100
|
||||
Subject: [PATCH] udisks2: Do not schedule update if pending already
|
||||
|
||||
Currently, the udisks2 volume monitor updates everything for each
|
||||
`/proc/mounts`, `/etc/fstab`, and udisks2 change. The update takes some
|
||||
time. If too many changes happen in a short timeframe, the udisks2
|
||||
volume monitor is not able to handle those events in a real-time. The
|
||||
pending events can be processed for a long time. Many of those updates
|
||||
are redundant though as the real changes were already reflected during
|
||||
the previous updates. This causes a high CPU load among others. Let's
|
||||
add small timeout that will allow to skip accumullated events.
|
||||
|
||||
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/713
|
||||
---
|
||||
monitor/udisks2/gvfsudisks2volumemonitor.c | 35 +++++++++++++++++++---
|
||||
1 file changed, 31 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
index c8864aea8..540683b22 100644
|
||||
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
@@ -68,8 +68,12 @@ struct _GVfsUDisks2VolumeMonitor
|
||||
|
||||
GSettings *lockdown_settings;
|
||||
gboolean readonly_lockdown;
|
||||
+
|
||||
+ gint update_id;
|
||||
};
|
||||
|
||||
+#define UPDATE_TIMEOUT 100 /* ms */
|
||||
+
|
||||
static UDisksClient *get_udisks_client_sync (GError **error);
|
||||
|
||||
static void update_all (GVfsUDisks2VolumeMonitor *monitor,
|
||||
@@ -148,6 +152,8 @@ gvfs_udisks2_volume_monitor_finalize (GObject *object)
|
||||
|
||||
g_clear_object (&monitor->lockdown_settings);
|
||||
|
||||
+ g_clear_handle_id (&monitor->update_id, g_source_remove);
|
||||
+
|
||||
G_OBJECT_CLASS (gvfs_udisks2_volume_monitor_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -425,12 +431,33 @@ gvfs_udisks2_volume_monitor_get_readonly_lockdown (GVfsUDisks2VolumeMonitor *mon
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
+static gboolean
|
||||
+update_func (gpointer user_data)
|
||||
+{
|
||||
+ GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
|
||||
+
|
||||
+ monitor->update_id = 0;
|
||||
+
|
||||
+ update_all (monitor, TRUE, FALSE);
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+schedule_update (GVfsUDisks2VolumeMonitor *monitor)
|
||||
+{
|
||||
+ if (monitor->update_id != 0)
|
||||
+ return;
|
||||
+
|
||||
+ monitor->update_id = g_timeout_add (UPDATE_TIMEOUT, update_func, monitor);
|
||||
+}
|
||||
+
|
||||
void
|
||||
gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor)
|
||||
{
|
||||
g_return_if_fail (GVFS_IS_UDISKS2_VOLUME_MONITOR (monitor));
|
||||
udisks_client_settle (monitor->client);
|
||||
- update_all (monitor, TRUE, FALSE);
|
||||
+ schedule_update (monitor);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
@@ -532,7 +559,7 @@ on_client_changed (UDisksClient *client,
|
||||
gpointer user_data)
|
||||
{
|
||||
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
|
||||
- update_all (monitor, TRUE, FALSE);
|
||||
+ schedule_update (monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -540,7 +567,7 @@ mountpoints_changed (GUnixMountMonitor *mount_monitor,
|
||||
gpointer user_data)
|
||||
{
|
||||
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
|
||||
- update_all (monitor, TRUE, FALSE);
|
||||
+ schedule_update (monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -548,7 +575,7 @@ mounts_changed (GUnixMountMonitor *mount_monitor,
|
||||
gpointer user_data)
|
||||
{
|
||||
GVfsUDisks2VolumeMonitor *monitor = GVFS_UDISKS2_VOLUME_MONITOR (user_data);
|
||||
- update_all (monitor, TRUE, FALSE);
|
||||
+ schedule_update (monitor);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
--
|
||||
GitLab
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
From 45a5612574a54bf4648cedafa5b977efb48293c9 Mon Sep 17 00:00:00 2001
|
||||
Date: Thu, 12 Sep 2024 13:27:04 +0200
|
||||
Subject: [PATCH] udisks2: Run update synchronously for internal changes
|
||||
|
||||
The commit 14dc69de introduced performance improvement by skipping
|
||||
accumulated mount, mount point and udisks2 client changes. That was
|
||||
achieved by running the update with a small delay. But this logic was
|
||||
mistakenly used for the `gvfs_udisks2_volume_monitor_update` function
|
||||
also. This function expects the update to happen synchronously. This
|
||||
leads to various issues e.g. `g_volume_get_mount` fails when called
|
||||
immediately after `g_volume_mount`. Let's run the update synchronously
|
||||
from the `gvfs_udisks2_volume_monitor_update` function to fix the
|
||||
mentioned issues.
|
||||
|
||||
Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/762
|
||||
---
|
||||
monitor/udisks2/gvfsudisks2volumemonitor.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
index 3a2015b29..f78f28d40 100644
|
||||
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
@@ -457,7 +457,11 @@ gvfs_udisks2_volume_monitor_update (GVfsUDisks2VolumeMonitor *monitor)
|
||||
{
|
||||
g_return_if_fail (GVFS_IS_UDISKS2_VOLUME_MONITOR (monitor));
|
||||
udisks_client_settle (monitor->client);
|
||||
- schedule_update (monitor);
|
||||
+
|
||||
+ if (monitor->update_id != 0)
|
||||
+ g_source_remove (monitor->update_id);
|
||||
+
|
||||
+ update_func (monitor);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
--
|
||||
GitLab
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,89 +0,0 @@
|
||||
Adapted https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/290
|
||||
|
||||
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
index 55feb07..f78f364 100644
|
||||
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
@@ -92,6 +92,7 @@ static void update_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
GList **removed_volumes,
|
||||
gboolean coldplug);
|
||||
static void update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
+ GHashTable *mount_points_by_path, /* gchar *path ~> GUnixMountPoint * */
|
||||
GList **added_volumes,
|
||||
GList **removed_volumes,
|
||||
gboolean coldplug);
|
||||
@@ -749,7 +750,7 @@ update_all (GVfsUDisks2VolumeMonitor *monitor,
|
||||
|
||||
update_drives (monitor, &added_drives, &removed_drives, coldplug);
|
||||
update_volumes (monitor, mount_entries, mount_points_by_path, &added_volumes, &removed_volumes, coldplug);
|
||||
- update_fstab_volumes (monitor, &added_volumes, &removed_volumes, coldplug);
|
||||
+ update_fstab_volumes (monitor, mount_points_by_path, &added_volumes, &removed_volumes, coldplug);
|
||||
update_mounts (monitor, mount_entries, mount_points_by_path, &added_mounts, &removed_mounts, coldplug);
|
||||
update_discs (monitor,
|
||||
&added_volumes, &removed_volumes,
|
||||
@@ -1619,16 +1620,9 @@ mount_point_has_device (GVfsUDisks2VolumeMonitor *monitor,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void
|
||||
-free_nonnull_unix_mount_point (gpointer ptr)
|
||||
-{
|
||||
- GUnixMountPoint *mount_point = ptr;
|
||||
- if (mount_point != NULL)
|
||||
- g_unix_mount_point_free (mount_point);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
+ GHashTable *mount_points_by_path, /* gchar *path ~> GUnixMountPoint * */
|
||||
GList **added_volumes,
|
||||
GList **removed_volumes,
|
||||
gboolean coldplug)
|
||||
@@ -1636,7 +1630,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
GHashTable *cur_mount_points; /* GUnixMountPoint * ~> GVfsUDisks2Volume * */
|
||||
GHashTableIter iter;
|
||||
gpointer key = NULL, value = NULL;
|
||||
- GList *new_mount_points, *l;
|
||||
GVfsUDisks2Volume *volume;
|
||||
|
||||
cur_mount_points = g_hash_table_new_full (gvfs_mount_point_hash, gvfs_mount_point_equal, NULL, g_object_unref);
|
||||
@@ -1651,10 +1644,10 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
g_hash_table_insert (cur_mount_points, mount_point, g_object_ref (volume));
|
||||
}
|
||||
|
||||
- new_mount_points = g_unix_mount_points_get (NULL);
|
||||
- for (l = new_mount_points; l != NULL; l = g_list_next (l))
|
||||
+ g_hash_table_iter_init (&iter, mount_points_by_path);
|
||||
+ while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
{
|
||||
- GUnixMountPoint *mount_point = l->data;
|
||||
+ GUnixMountPoint *mount_point = value;
|
||||
|
||||
/* use the mount points that we want to include */
|
||||
if (should_include_mount_point (monitor, mount_point) &&
|
||||
@@ -1666,7 +1659,7 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
{
|
||||
volume = gvfs_udisks2_volume_new (monitor,
|
||||
NULL, /* block */
|
||||
- mount_point,
|
||||
+ g_unix_mount_point_copy (mount_point), /* adopts the mount_point */
|
||||
NULL, /* drive */
|
||||
NULL, /* activation_root */
|
||||
coldplug);
|
||||
@@ -1683,7 +1676,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
|
||||
g_hash_table_add (monitor->fstab_volumes, g_object_ref (volume));
|
||||
*added_volumes = g_list_prepend (*added_volumes, g_steal_pointer (&volume));
|
||||
- l->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1699,8 +1691,6 @@ update_fstab_volumes (GVfsUDisks2VolumeMonitor *monitor,
|
||||
g_hash_table_remove (monitor->fstab_volumes, volume);
|
||||
}
|
||||
|
||||
- g_list_free_full (new_mount_points, free_nonnull_unix_mount_point);
|
||||
-
|
||||
g_hash_table_unref (cur_mount_points);
|
||||
}
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
From 3e3691a59b69aeafac4288e0599fca3eb4cb02f3 Mon Sep 17 00:00:00 2001
|
||||
Date: Tue, 3 Feb 2026 19:15:32 +0100
|
||||
Subject: [PATCH] udisks2: Fix memory corruption with duplicate mount paths
|
||||
|
||||
Calling g_hash_table_insert on a key that already exists in the table frees
|
||||
the old value and the *new* key, thus leaving the old key pointing to free'd
|
||||
memory. g_hash_table_replace instead frees the old value and key together
|
||||
and inserts the new value and key into the table.
|
||||
---
|
||||
monitor/udisks2/gvfsudisks2volumemonitor.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/monitor/udisks2/gvfsudisks2volumemonitor.c b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
index c57249e5..aa1ca7a3 100644
|
||||
--- a/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
+++ b/monitor/udisks2/gvfsudisks2volumemonitor.c
|
||||
@@ -730,7 +730,7 @@ update_all (GVfsUDisks2VolumeMonitor *monitor,
|
||||
for (link = entries; link != NULL; link = g_list_next (link))
|
||||
{
|
||||
GUnixMountEntry *mount_entry = link->data;
|
||||
- g_hash_table_insert (mount_entries, (gpointer) g_unix_mount_get_mount_path (mount_entry), mount_entry);
|
||||
+ g_hash_table_replace (mount_entries, (gpointer) g_unix_mount_get_mount_path (mount_entry), mount_entry);
|
||||
}
|
||||
/* the mount_entries took ownership of the mount entry objects */
|
||||
g_list_free (entries);
|
||||
@@ -742,7 +742,7 @@ update_all (GVfsUDisks2VolumeMonitor *monitor,
|
||||
for (link = points; link != NULL; link = g_list_next (link))
|
||||
{
|
||||
GUnixMountPoint *mount_point = link->data;
|
||||
- g_hash_table_insert (mount_points_by_path, (gpointer) g_unix_mount_point_get_mount_path (mount_point), mount_point);
|
||||
+ g_hash_table_replace (mount_points_by_path, (gpointer) g_unix_mount_point_get_mount_path (mount_point), mount_point);
|
||||
}
|
||||
/* the mount_points_by_path took ownership of the mount point objects */
|
||||
g_list_free (points);
|
||||
--
|
||||
GitLab
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
Name: gvfs
|
||||
Version: 1.36.2
|
||||
Release: 21%{?dist}
|
||||
Release: 16%{?dist}
|
||||
Summary: Backends for the gio framework in GLib
|
||||
|
||||
License: GPLv3 and LGPLv2+ and BSD and MPLv2.0
|
||||
@ -80,48 +80,6 @@ Patch15: google-performance-fixes.patch
|
||||
Patch16: trash-Add-support-for-x-gvfs-notrash-option-to-ignor.patch
|
||||
Patch17: trash-Sync-trash-dir-items-when-files-change.patch
|
||||
|
||||
# https://issues.redhat.com/browse/RHEL-52342
|
||||
Patch18: trash-Add-support-for-x-gvfs-trash-mount-option.patch
|
||||
|
||||
# https://issues.redhat.com/browse/RHEL-45163
|
||||
Patch19: daemon-Add-support-for-edit-mode.patch
|
||||
Patch20: gdaemonfile-Use-edit-mode-when-private-edit-flag-is-.patch
|
||||
Patch21: fuse-Use-edit-mode-instead-of-returning-ENOTSUP.patch
|
||||
Patch22: smb-Fail-when-initial_offset-can-t-be-determined.patch
|
||||
Patch23: smb-Disable-seek-support-when-appening.patch
|
||||
Patch24: smb-Fix-offset-after-truncate-when-appending.patch
|
||||
Patch25: smb-Implement-support-for-edit-mode.patch
|
||||
|
||||
# https://issues.redhat.com/browse/RHEL-76484
|
||||
Patch26: udisks2-monitor-performance-202.patch
|
||||
Patch27: udisks2-monitor-performance-230.patch
|
||||
Patch28: udisks2-monitor-performance-273.patch
|
||||
Patch29: udisks2-monitor-performance-290.patch
|
||||
Patch30: udisks2-monitor-performance-297.patch
|
||||
|
||||
# Improve trash backend performance
|
||||
# https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/287
|
||||
# https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/175
|
||||
# https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/169
|
||||
# https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/11
|
||||
Patch31: backend-Prevent-usage-of-NULL.patch
|
||||
Patch32: trash-Add-is_root-function.patch
|
||||
Patch33: trash-Remove-unused-ui_hook-property.patch
|
||||
Patch34: trash-Remove-unused-is_homedir-property.patch
|
||||
Patch35: trash-Do-not-create-monitors-for-non-root-items.patch
|
||||
Patch36: trash-Run-blocking-methods-on-a-thread-pool.patch
|
||||
Patch37: trash-Add-worker-thread.patch
|
||||
Patch38: trash-Chain-up-finalize.patch
|
||||
Patch39: trash-Rate-limit-mount-updates.patch
|
||||
Patch40: trash-Add-debug-prints-for-mounts-handling.patch
|
||||
Patch41: trash-Use-GHashTable-for-mount-tracking.patch
|
||||
Patch42: trash-Use-GHashTable-for-trash-directory-items.patch
|
||||
Patch43: trash-Rate-limit-size-change-notifications.patch
|
||||
Patch44: trash-Use-weak-refs-for-monitor-lifecycle.patch
|
||||
Patch45: trash-Defer-mount-monitoring-to-active-watchers-only.patch
|
||||
Patch46: daemon-Add-process-name-to-debug-handler-log.patch
|
||||
Patch47: trash-Skip-mount-table-reparsing-when-unchanged.patch
|
||||
|
||||
BuildRequires: pkgconfig
|
||||
BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version}
|
||||
BuildRequires: pkgconfig(dbus-glib-1)
|
||||
@ -512,22 +470,6 @@ killall -USR1 gvfsd >&/dev/null || :
|
||||
%{_datadir}/installed-tests
|
||||
|
||||
%changelog
|
||||
* Tue Jun 02 2026 Ondrej Holy <oholy@redhat.com> - 1.36.2-21
|
||||
- Improve trash backend performance
|
||||
Resolves: RHEL-127445
|
||||
|
||||
* Fri Feb 06 2026 Milan Crha <mcrha@redhat.com> - 1.36.2-20
|
||||
- udisks2: Correct add to hash table for items which can clash in the monitor (RHEL-76484)
|
||||
|
||||
* Wed Jan 21 2026 Milan Crha <mcrha@redhat.com> - 1.36.2-19
|
||||
- udisks2: Use hash table for quicker lookups in the monitor (RHEL-76484)
|
||||
|
||||
* Thu Feb 13 2025 Ondrej Holy <oholy@redhat.com> - 1.36.2-18
|
||||
- Add edit mode support for smb backend (RHEL-45163)
|
||||
|
||||
* Thu Sep 26 2024 Ondrej Holy <oholy@redhat.com> - 1.36.2-17
|
||||
- Add support for x-gvfs-trash mount option (RHEL-52342)
|
||||
|
||||
* Wed Dec 06 2023 Ondrej Holy <oholy@redhat.com> - 1.36.2-16
|
||||
- Sync trash dir items when files change (RHEL-2824)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user