Skip to content

Commit 2b1fb7f

Browse files
author
lianzhi chang
committed
Fix the problem that btrfs multi-partition cannot be unmounted
udisks state_check_mounted_fs() gets mounts before calling udisks state_check_mounted_fs_entry() in a loop. Signed-off-by: lianzhi chang <[email protected]>
1 parent 0af02e3 commit 2b1fb7f

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

src/udisksmountmonitor.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,33 @@ udisks_mount_monitor_ensure (UDisksMountMonitor *monitor)
709709
g_mutex_unlock (&monitor->mounts_mutex);
710710
}
711711

712+
/**
713+
* udisks_mount_monitor_get_mounts:
714+
* @monitor: A #UDisksMountMonitor.
715+
*
716+
* Gets all #UDisksMount objects.
717+
*
718+
* Returns: A #GList of #UDisksMount objects. The returned list must
719+
* be freed with g_list_free() after each element has been freed with
720+
* g_object_unref().
721+
*/
722+
GList *
723+
udisks_mount_monitor_get_mounts (UDisksMountMonitor *monitor)
724+
{
725+
GList *ret;
726+
727+
ret = NULL;
728+
729+
g_mutex_lock (&monitor->mounts_mutex);
730+
ret = g_list_copy_deep (monitor->mounts, (GCopyFunc) udisks_g_object_ref_copy, NULL);
731+
g_mutex_unlock (&monitor->mounts_mutex);
732+
733+
/* Sort the list to ensure that shortest mount paths appear first */
734+
ret = g_list_sort (ret, (GCompareFunc) udisks_mount_compare);
735+
736+
return ret;
737+
}
738+
712739
/**
713740
* udisks_mount_monitor_get_mounts_for_dev:
714741
* @monitor: A #UDisksMountMonitor.

src/udisksmountmonitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ G_BEGIN_DECLS
3131

3232
GType udisks_mount_monitor_get_type (void) G_GNUC_CONST;
3333
UDisksMountMonitor *udisks_mount_monitor_new (void);
34+
GList *udisks_mount_monitor_get_mounts (UDisksMountMonitor *monitor);
3435
GList *udisks_mount_monitor_get_mounts_for_dev (UDisksMountMonitor *monitor,
3536
dev_t dev);
3637
gboolean udisks_mount_monitor_is_dev_in_use (UDisksMountMonitor *monitor,

src/udisksstate.c

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,49 @@ lookup_asv (GVariant *asv,
569569

570570
/* ---------------------------------------------------------------------------------------------------- */
571571

572+
/**
573+
* udisks_mount_monitor_get_mounts_for_dev:
574+
* @mounts: A #UDisksMount.
575+
* @dev: A #dev_t device number.
576+
*
577+
* Gets all #UDisksMount objects for @dev.
578+
*
579+
* Returns: A #GList of #UDisksMount objects. The returned list must
580+
* be freed with g_list_free() after each element has been freed with
581+
* g_object_unref().
582+
*/
583+
static GList *
584+
udisks_state_get_mounts_for_dev (GList *mounts,
585+
dev_t dev)
586+
{
587+
GList *ret;
588+
GList *l;
589+
590+
ret = NULL;
591+
592+
for (l = mounts; l != NULL; l = l->next)
593+
{
594+
UDisksMount *mount = UDISKS_MOUNT (l->data);
595+
596+
if (udisks_mount_get_dev (mount) == dev)
597+
{
598+
ret = g_list_prepend (ret, g_object_ref (mount));
599+
}
600+
}
601+
602+
/* Sort the list to ensure that shortest mount paths appear first */
603+
ret = g_list_sort (ret, (GCompareFunc) udisks_mount_compare);
604+
605+
return ret;
606+
}
607+
572608
/* returns TRUE if the entry should be kept */
573609
static gboolean
574610
udisks_state_check_mounted_fs_entry (UDisksState *state,
575611
GVariant *value,
576612
GArray *devs_to_clean,
577-
dev_t match_block_device)
613+
dev_t match_block_device,
614+
GList *monitor_mounts)
578615
{
579616
const gchar *mount_point_str;
580617
gchar mount_point[PATH_MAX] = { '\0', };
@@ -590,7 +627,6 @@ udisks_state_check_mounted_fs_entry (UDisksState *state,
590627
gboolean is_mounted;
591628
gboolean device_exists;
592629
gboolean device_to_be_cleaned;
593-
UDisksMountMonitor *monitor;
594630
GUdevClient *udev_client;
595631
GUdevDevice *udev_device;
596632
guint n;
@@ -608,8 +644,6 @@ udisks_state_check_mounted_fs_entry (UDisksState *state,
608644
details = NULL;
609645
locked = FALSE;
610646

611-
monitor = udisks_daemon_get_mount_monitor (state->daemon);
612-
613647
g_variant_get (value,
614648
"{&s@a{sv}}",
615649
&mount_point_str,
@@ -668,7 +702,7 @@ udisks_state_check_mounted_fs_entry (UDisksState *state,
668702
/* udisks_debug ("Validating mounted-fs entry for mount point %s", mount_point); */
669703

670704
/* Figure out if still mounted */
671-
mounts = udisks_mount_monitor_get_mounts_for_dev (monitor, block_device);
705+
mounts = udisks_state_get_mounts_for_dev (monitor_mounts, block_device);
672706
for (l = mounts; l != NULL; l = l->next)
673707
{
674708
UDisksMount *mount = UDISKS_MOUNT (l->data);
@@ -870,15 +904,21 @@ udisks_state_check_mounted_fs (UDisksState *state,
870904
{
871905
GVariantIter iter;
872906
GVariant *child;
907+
GList *mounts;
908+
UDisksMountMonitor *monitor;
909+
910+
monitor = udisks_daemon_get_mount_monitor (state->daemon);
911+
mounts = udisks_mount_monitor_get_mounts(monitor);
873912
g_variant_iter_init (&iter, value);
874913
while ((child = g_variant_iter_next_value (&iter)) != NULL)
875914
{
876-
if (udisks_state_check_mounted_fs_entry (state, child, devs_to_clean, match_block_device))
915+
if (udisks_state_check_mounted_fs_entry (state, child, devs_to_clean, match_block_device, mounts))
877916
g_variant_builder_add_value (&builder, child);
878917
else
879918
changed = TRUE;
880919
g_variant_unref (child);
881920
}
921+
g_list_free_full (mounts, g_object_unref);
882922
g_variant_unref (value);
883923
}
884924

0 commit comments

Comments
 (0)