From d8ea9d5a3fc6dee4673010e117ce3d3e350fc3ac Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Wed, 9 May 2012 12:54:03 -0400 Subject: [PATCH] Simplify loop device checking ... and never automatically tear down loop devices. Signed-off-by: David Zeuthen --- src/udiskscleanup.c | 171 ++++++++++------------------------------------------ 1 file changed, 32 insertions(+), 139 deletions(-) diff --git a/src/udiskscleanup.c b/src/udiskscleanup.c index 47e2555..4ec1fd7 100644 --- a/src/udiskscleanup.c +++ b/src/udiskscleanup.c @@ -1506,34 +1506,14 @@ udisks_cleanup_check_loop_entry (UDisksCleanup *cleanup, GArray *devs_to_clean) { const gchar *loop_device; - GVariant *details; - gchar *s; - gboolean keep; - gboolean is_setup; - gboolean has_backing_device; - gboolean backing_device_mounted; - gboolean attempt_no_cleanup; - GVariant *backing_file_value; - GVariant *backing_file_device_value; + GVariant *details = NULL; + gboolean keep = FALSE; + GVariant *backing_file_value = NULL; const gchar *backing_file; - dev_t backing_file_device; GUdevClient *udev_client; - struct stat loop_device_statbuf; - gint loop_device_fd; - struct loop_info64 li64; - UDisksMountMonitor *monitor; - GUdevDevice *udev_backing_file_device; - - keep = FALSE; - attempt_no_cleanup = FALSE; - is_setup = FALSE; - has_backing_device = FALSE; - backing_device_mounted = FALSE; - backing_file_value = NULL; - backing_file_device_value = NULL; - details = NULL; + GUdevDevice *device = NULL; + const gchar *sysfs_backing_file; - monitor = udisks_daemon_get_mount_monitor (cleanup->daemon); udev_client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (cleanup->daemon)); g_variant_get (value, @@ -1544,155 +1524,68 @@ udisks_cleanup_check_loop_entry (UDisksCleanup *cleanup, backing_file_value = lookup_asv (details, "backing-file"); if (backing_file_value == NULL) { + gchar *s; s = g_variant_print (value, TRUE); udisks_error ("loop entry %s is invalid: no backing-file key/value pair", s); g_free (s); - attempt_no_cleanup = TRUE; goto out; } backing_file = g_variant_get_bytestring (backing_file_value); - backing_file_device_value = lookup_asv (details, "backing-file-device"); - if (backing_file_device_value == NULL) + /* check the loop device is still set up */ + device = g_udev_client_query_by_device_file (udev_client, loop_device); + if (device == NULL) { - s = g_variant_print (value, TRUE); - udisks_error ("loop entry %s is invalid: no backing-file-device key/value pair", s); - g_free (s); - attempt_no_cleanup = TRUE; + udisks_info ("no udev device for %s", loop_device); goto out; } - backing_file_device = g_variant_get_uint64 (backing_file_device_value); - - if (backing_file_device == 0 || major (backing_file_device) == 0) + if (g_udev_device_get_sysfs_attr (device, "loop/offset") == NULL) { - /* major==0 -> not regular block device ... could be e.g. NFS ... - * for now, just assume it's still there and mounted - */ - keep = TRUE; + udisks_info ("loop device %s is not setup (no loop/offset sysfs file)", loop_device); goto out; } - if (stat (loop_device, &loop_device_statbuf) != 0) - { - udisks_error ("error statting %s: %m", loop_device); - attempt_no_cleanup = TRUE; - goto out; - } - loop_device_fd = open (loop_device, O_RDONLY); - if (loop_device_fd == -1 ) - { - udisks_info ("error opening %s: %m", loop_device); - attempt_no_cleanup = TRUE; - goto out; - } - memset (&li64, '\0', sizeof (struct loop_info64)); - if (ioctl (loop_device_fd, LOOP_GET_STATUS64, &li64) == -1) - { - udisks_info ("error issuing LOOP_GET_STATUS64 ioctl on %s: %m", loop_device); - attempt_no_cleanup = TRUE; - close (loop_device_fd); - goto out; - } - close (loop_device_fd); - if (strncmp ((const char *) li64.lo_file_name, backing_file, LO_NAME_SIZE - 1) != 0) + /* Check the loop device set up, is the one that _we_ set up + * + * Note that drivers/block/loop.c:loop_attr_backing_file_show() uses d_path() + * on lo_file_name so in the event that the underlying fs was unmounted + * (just 'umount -l /path/to/fs/holding/backing/file to try) it cuts + * off the mount path.... in this case we simply just give up managing + * the loop device + */ + sysfs_backing_file = g_udev_device_get_sysfs_attr (device, "loop/backing_file"); + if (g_strcmp0 (sysfs_backing_file, backing_file) != 0) { - udisks_error ("unexpected name for device %s - expected `%s' but got `%s'", - loop_device, backing_file, li64.lo_file_name); - attempt_no_cleanup = TRUE; + udisks_notice ("unexpected name for %s - expected `%s' but got `%s'", + loop_device, backing_file, sysfs_backing_file); goto out; } - is_setup = TRUE; - - /* check with udev if the backing device exists and is still mounted */ - udev_backing_file_device = g_udev_client_query_by_device_number (udev_client, - G_UDEV_DEVICE_TYPE_BLOCK, - backing_file_device); - if (udev_backing_file_device != NULL) - { - GList *mounts; - - has_backing_device = TRUE; - g_object_unref (udev_backing_file_device); - - /* and if it's still mounted */ - mounts = udisks_mount_monitor_get_mounts_for_dev (monitor, backing_file_device); - if (mounts != NULL) - backing_device_mounted = TRUE; - g_list_foreach (mounts, (GFunc) g_object_unref, NULL); - g_list_free (mounts); - } /* OK, entry is valid - keep it around */ - if (is_setup && has_backing_device && backing_device_mounted) - keep = TRUE; + keep = TRUE; out: if (check_only && !keep) { - g_array_append_val (devs_to_clean, loop_device_statbuf.st_rdev); + if (device != NULL) + { + dev_t dev_number = g_udev_device_get_device_number (device); + g_array_append_val (devs_to_clean, dev_number); + } keep = TRUE; goto out2; } if (!keep) { - if (!attempt_no_cleanup) - { - if (is_setup) - { - gchar *escaped_loop_device_file; - gchar *error_message; - - if (!has_backing_device) - udisks_notice ("Cleaning up loop device %s (backing device %d:%d no longer exist)", - loop_device, - major (backing_file_device), minor (backing_file_device)); - else - udisks_notice ("Cleaning up loop device %s (backing device %d:%d no longer mounted)", - loop_device, - major (backing_file_device), minor (backing_file_device)); - - error_message = NULL; - escaped_loop_device_file = udisks_daemon_util_escape_and_quote (loop_device); - if (!udisks_daemon_launch_spawned_job_sync (cleanup->daemon, - NULL, /* UDisksObject */ - NULL, /* GCancellable */ - 0, /* uid_t run_as_uid */ - 0, /* uid_t run_as_euid */ - NULL, /* gint *out_status */ - &error_message, - NULL, /* input_string */ - "losetup -d %s", - escaped_loop_device_file)) - { - udisks_error ("Error cleaning up loop device %s: %s", - loop_device, error_message); - g_free (escaped_loop_device_file); - g_free (error_message); - /* keep the entry so we can clean it up later */ - keep = TRUE; - goto out2; - } - g_free (escaped_loop_device_file); - g_free (error_message); - } - else - { - udisks_notice ("loop device %s was manually deleted", loop_device); - } - } - else - { - udisks_notice ("Loop device %s was deleted", loop_device); - } + udisks_notice ("No longer watching loop device %s", loop_device); } out2: + g_clear_object (&device); if (backing_file_value != NULL) g_variant_unref (backing_file_value); - if (backing_file_device_value != NULL) - g_variant_unref (backing_file_device_value); if (details != NULL) g_variant_unref (details); return keep; -- 2.7.4