From 6121d5437d7800876567fd08b6020ca1d72eeaac Mon Sep 17 00:00:00 2001 From: Vratislav Podzimek Date: Fri, 20 Oct 2017 13:24:20 +0200 Subject: [PATCH] Add and use a service for cleaning up mount point directories When udisks2 is used for mounting devices, it may need to create the mount point directory. If unmount happens later, udisks2 cleans after itself and removes the mount point directory. However, if the unmount happens during reboot, the udisks2 daemon may already be terminated not having a chance to do the cleanup. We need a different mechanism to do the job in such cases. systemd provides us with such a mechanism so let's make use of it. Resolves: rhbz#1384796 Signed-off-by: Vratislav Podzimek --- data/Makefile.am | 6 ++-- data/clean-mount-point@.service | 10 +++++++ packaging/udisks2.spec | 1 + src/Makefile.am | 3 +- src/udiskslinuxfilesystem.c | 61 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 data/clean-mount-point@.service diff --git a/data/Makefile.am b/data/Makefile.am index 83af330..9b8073a 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -15,14 +15,14 @@ dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) $(dbusconf_DATA): $(dbusconf_in_files) Makefile cp $< $@ -systemdservice_in_files = udisks2.service.in +systemdservice_in_files = udisks2.service.in clean-mount-point@.service if HAVE_SYSTEMD systemdservicedir = $(systemdsystemunitdir) systemdservice_DATA = $(systemdservice_in_files:.service.in=.service) -$(systemdservice_DATA): $(systemdservice_in_files) Makefile - @sed -e "s|\@udisksdprivdir\@|$(libexecdir)/udisks2|" $< > $@ +$(systemdservice_DATA): udisks2.service.in Makefile + @sed -e "s|\@udisksdprivdir\@|$(libexecdir)/udisks2|" udisks2.service.in > udisks2.service endif udevrulesdir = $(udevdir)/rules.d diff --git a/data/clean-mount-point@.service b/data/clean-mount-point@.service new file mode 100644 index 0000000..83edceb --- /dev/null +++ b/data/clean-mount-point@.service @@ -0,0 +1,10 @@ +[Unit] +Description=Clean the %f mount point +Before=%i.mount +BindsTo=%i.mount +DefaultDependencies=no + +[Service] +Type=oneshot +RemainAfterExit=true +ExecStop=/bin/rm -fd %f diff --git a/src/Makefile.am b/src/Makefile.am index 396ab4e..3b22cca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -113,7 +113,8 @@ libudisks_daemon_la_LIBADD = \ $(GIO_LIBS) \ $(GMODULE_LIBS) \ $(GUDEV_LIBS) \ - $(BLOCKDEV_LIBS) \ + $(BLOCKDEV_LIBS) \ + -lbd_utils \ $(LIBATASMART_LIBS) \ $(POLKIT_GOBJECT_1_LIBS) \ $(ACL_LIBS) \ diff --git a/src/udiskslinuxfilesystem.c b/src/udiskslinuxfilesystem.c index 4cd2784..2910181 100644 --- a/src/udiskslinuxfilesystem.c +++ b/src/udiskslinuxfilesystem.c @@ -86,9 +86,11 @@ G_DEFINE_TYPE_WITH_CODE (UDisksLinuxFilesystem, udisks_linux_filesystem, UDISKS_ G_IMPLEMENT_INTERFACE (UDISKS_TYPE_FILESYSTEM, filesystem_iface_init)); #ifdef HAVE_FHS_MEDIA -# define MOUNT_BASE "/media" +#define MOUNT_BASE "/media" +#define MOUNT_BASE_PERSISTENT TRUE #else -# define MOUNT_BASE "/run/media" +#define MOUNT_BASE "/run/media" +#define MOUNT_BASE_PERSISTENT FALSE #endif /* ---------------------------------------------------------------------------------------------------- */ @@ -833,6 +835,7 @@ add_acl (const gchar *path, * @gid: group id of the calling user * @user_name: user name of the calling user * @fs_type: The file system type to mount with + * @persistent: if the mount point is persistent (survives reboot) or not * @error: Return location for error or %NULL. * * Calculates the mount point to use. @@ -846,6 +849,7 @@ calculate_mount_point (UDisksDaemon *daemon, gid_t gid, const gchar *user_name, const gchar *fs_type, + gboolean *persistent, GError **error) { UDisksLinuxBlockObject *object = NULL; @@ -889,6 +893,7 @@ calculate_mount_point (UDisksDaemon *daemon, if (!fs_shared && (user_name != NULL && strstr (user_name, "/") == NULL)) { mount_dir = g_strdup_printf (MOUNT_BASE "/%s", user_name); + *persistent = MOUNT_BASE_PERSISTENT; if (!g_file_test (mount_dir, G_FILE_TEST_EXISTS)) { /* First ensure that MOUNT_BASE exists */ @@ -933,8 +938,10 @@ calculate_mount_point (UDisksDaemon *daemon, } } /* otherwise fall back to mounting in /media */ - if (mount_dir == NULL) + if (mount_dir == NULL) { mount_dir = g_strdup ("/media"); + *persistent = TRUE; + } /* NOTE: UTF-8 has the nice property that valid UTF-8 strings only contains * the byte 0x2F if it's for the '/' character (U+002F SOLIDUS). @@ -1135,6 +1142,49 @@ is_system_managed (UDisksBlock *block, return ret; } +static void trigger_mpoint_cleanup (const gchar *mount_point) +{ + const gchar *argv[] = {"systemctl", "start", NULL, NULL}; + GError *error = NULL; + gchar *escaped_mpoint = NULL; + gsize len = 0; + + if (g_str_has_prefix (mount_point, "/")) + mount_point++; + else + udisks_warning ("Invalid mount point given to trigger_mpoint_cleanup(): %s", + mount_point); + + /* start with the mount point without the leading '/' */ + escaped_mpoint = g_strdup (mount_point); + + /* and replace all '/'s with '-'s */ + for (gchar *letter = escaped_mpoint; *letter != '\0'; letter++, len++) + { + if (*letter == '/') + *letter = '-'; + } + + /* remove the potential trailing '-' (would happen if the given mount_point + has a trailing '/') */ + if (escaped_mpoint[len - 1] == '-') + escaped_mpoint[len - 1] = '\0'; + + argv[2] = g_strdup_printf ("clean-mount-point@%s", escaped_mpoint); + + if (!bd_utils_exec_and_report_error (argv, NULL, &error) && (error != NULL)) + { + /* this is a best-effort mechanism, if it fails, just log warning and move + on */ + udisks_warning ("Failed to setup systemd-based mount point cleanup: %s", + error->message); + g_clear_error (&error); + } + + g_free (escaped_mpoint); + g_free ((gchar *) argv[2]); +} + /* ---------------------------------------------------------------------------------------------------- */ /* runs in thread dedicated to handling @invocation */ @@ -1154,6 +1204,7 @@ handle_mount (UDisksFilesystem *filesystem, gchar *fs_type_to_use = NULL; gchar *mount_options_to_use = NULL; gchar *mount_point_to_use = NULL; + gboolean mpoint_persistent = TRUE; gchar *fstab_mount_options = NULL; gchar *caller_user_name = NULL; GError *error = NULL; @@ -1443,6 +1494,7 @@ handle_mount (UDisksFilesystem *filesystem, caller_gid, caller_user_name, fs_type_to_use, + &mpoint_persistent, &error); if (mount_point_to_use == NULL) { @@ -1487,6 +1539,9 @@ handle_mount (UDisksFilesystem *filesystem, else udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, NULL); + if (mpoint_persistent) + trigger_mpoint_cleanup (mount_point_to_use); + /* update the mounted-fs file */ udisks_state_add_mounted_fs (state, mount_point_to_use, -- 2.9.5