block: Improve stability of unmount 25/220525/1 submit/tizen_5.5/20191219.081950
authorYunmi Ha <yunmi.ha@samsung.com>
Mon, 2 Dec 2019 01:57:01 +0000 (10:57 +0900)
committerYunmi Ha <yunmi.ha@samsung.com>
Thu, 19 Dec 2019 07:15:42 +0000 (07:15 +0000)
- Using AddPowerOffWait/RemovePowerOffWait method of deviced.
- Change unmount processing order

Change-Id: I8754f1d3b732f15c5aa77a2233d918578e9c2aae
Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
(cherry picked from commit 0a4f7ab47c2997a8020c2ad29e01eab5f7cea578)

src/block/block.c
src/block/utils.c
src/block/utils.h

index 04ac236..f48dede 100644 (file)
@@ -78,6 +78,8 @@
 #define TIMEOUT_MAKE_OBJECT     500 /* milliseconds */
 
 #define SIGNAL_POWEROFF_STATE  "ChangeState"
+#define METHOD_ADD_POWEROFF_WAIT       "AddPowerOffWait"
+#define METHOD_REMOVE_POWEROFF_WAIT    "RemovePowerOffWait"
 
 #define BLOCK_DEVICE_ADDED      "DeviceAdded"
 #define BLOCK_DEVICE_REMOVED    "DeviceRemoved"
@@ -213,6 +215,7 @@ static fd_handler_h phandler;
 static bool block_control = false;
 static bool block_boot = false;
 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool add_poweroff_wait = false;
 
 /* Assume there is only one physical internal storage */
 static int dev_internal = -1;
@@ -229,6 +232,7 @@ static void remove_operation(struct block_device *bdev);
 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
 static int change_mount_point(struct block_device *bdev, const char *mount_point);
+static void terminate_threads(void);
 
 #define nullstr(x) (x ? x : "")
 static GVariant *block_data_to_gvariant(struct block_data *data, int flags);
@@ -1390,52 +1394,40 @@ static int block_unmount(struct block_device *bdev,
 
        _I("Execute force unmount.");
        /* Force Unmount Scenario */
-       while (1) {
-               switch (retry++) {
-               case 0:
-                       /* Mobile specific:
-                        * should unmount the below vconf key. */
-                       if ((data->block_type == BLOCK_MMC_DEV ||
-                               data->block_type == BLOCK_EXTENDEDSD_DEV) &&
-                               data->primary) {
-                               /* At first, notify to other app
-                                * who already access sdcard */
-                               _I("Notify to other app who already access sdcard.");
-                               vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
-                                               VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
-                       }
-                       break;
-               case 1:
-                       /* Second, kill app with SIGTERM */
-                       _I("Kill app with SIGTERM.");
-                       terminate_process(data->mount_point, false);
-                       break;
-               case 2:
-                       /* Last time, kill app with SIGKILL */
-                       _I("Kill app with SIGKILL.");
-                       terminate_process(data->mount_point, true);
-                       break;
-               default:
-                       if (umount2(data->mount_point, MNT_DETACH) != 0) {
-                               _I("Failed to unmount with lazy option: %d",
-                                               errno);
-                               return -errno;
-                       }
-                       goto out;
-               }
 
-               /* it takes some seconds til other app completely clean up */
-               time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
+       /* Mobile specific:
+        * should unmount the below vconf key. */
+       if ((data->block_type == BLOCK_MMC_DEV ||
+               data->block_type == BLOCK_EXTENDEDSD_DEV) &&
+               data->primary) {
+               /* At first, notify to other app
+                * who already access sdcard */
+               _I("Notify to other app who already access sdcard.");
+               vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
+                               VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
+       }
+
+       sync();
+       if (umount2(data->mount_point, MNT_DETACH) != 0) {
+               _I("Failed to unmount with lazy option: %m");
+               return -errno;
+       }
+
+       time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
+
+       while (retry++ < UNMOUNT_RETRY) {
+               _I("Kill app with SIGTERM.");
+               terminate_process(data->devnode, false);
                nanosleep(&time, NULL);
 
-               print_open_files(data->mount_point);
+               _I("Kill app with SIGKILL.");
+               terminate_process(data->devnode, true);
+               nanosleep(&time, NULL);
 
-               r = mmc_check_and_unmount(data->mount_point);
-               if (!r) {
-                       _D("Success to unmount '%s'.", data->mount_point);
+               if (!is_in_use_partition(data->devnode))
                        break;
-               }
        }
+       sync();
 
 out:
        data->state = BLOCK_UNMOUNT;
@@ -2703,6 +2695,16 @@ static void booting_done(void)
        /* if there is the attached device, try to mount */
        block_init_from_udev_enumerate();
 
+       ret = dbus_handle_method_sync(DEVICED_BUS_NAME,
+               DEVICED_PATH_POWEROFF,
+               DEVICED_INTERFACE_POWEROFF,
+               METHOD_ADD_POWEROFF_WAIT,
+               NULL, NULL);
+       if (ret < 0)
+               _E("Failed to call "METHOD_ADD_POWEROFF_WAIT" method.");
+       else
+               add_poweroff_wait = true;
+
        block_boot = true;
 }
 
@@ -2715,6 +2717,8 @@ static void block_poweroff(GDBusConnection  *conn,
                gpointer data)
 {
        static int status = 0;
+       int ret;
+
        if (status > 0)
                return;
        status = 1;
@@ -2722,6 +2726,19 @@ static void block_poweroff(GDBusConnection  *conn,
        /* unregister mmc uevent control routine */
        unregister_udev_uevent_control(&uh);
        remove_whole_block_device();
+       terminate_threads();
+
+       if (add_poweroff_wait) {
+               ret = dbus_handle_method_sync(DEVICED_BUS_NAME,
+                       DEVICED_PATH_POWEROFF,
+                       DEVICED_INTERFACE_POWEROFF,
+                       METHOD_REMOVE_POWEROFF_WAIT,
+                       NULL, NULL);
+               if (ret < 0)
+                       _E("Failed to call "METHOD_REMOVE_POWEROFF_WAIT" method.");
+               else
+                       add_poweroff_wait = false;
+       }
 }
 
 static void uevent_block_handler(struct udev_device *dev)
@@ -3787,6 +3804,18 @@ static void block_exit(void *data)
        /* exit pipe */
        pipe_exit();
 
+       if (add_poweroff_wait) {
+               ret = dbus_handle_method_sync(DEVICED_BUS_NAME,
+                       DEVICED_PATH_POWEROFF,
+                       DEVICED_INTERFACE_POWEROFF,
+                       METHOD_REMOVE_POWEROFF_WAIT,
+                       NULL, NULL);
+               if (ret < 0)
+                       _E("Failed to call "METHOD_REMOVE_POWEROFF_WAIT" method.");
+               else
+                       add_poweroff_wait = false;
+       }
+
        block_control = false;
 }
 
index 909c8a4..1c283ba 100644 (file)
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
@@ -127,6 +127,38 @@ int terminate_process(const char *partition, bool force)
        return run_child(argc, argv);
 }
 
+//If no process accesses the partition, return false
+//If at least one process access the partition, return true
+bool is_in_use_partition(const char *partition)
+{
+       FILE *fp;
+       char *cmd = NULL;
+       char *line = NULL;
+       size_t len = 0;
+       bool ret = false;
+
+       if (asprintf(&cmd, "/usr/bin/fuser -m %s", partition) < 0) {
+               _E("Failed to call asprintf: %m");
+               return false;
+       }
+
+       _D("cmd=%s\n", cmd);
+       fp = popen(cmd, "r");
+       free(cmd);
+       if (fp == NULL)
+               return false;
+
+       if (getline(&line, &len, fp) != -1) {
+               if (strtok(line, " ") != NULL)
+                       ret = true;
+       }
+
+       free(line);
+       pclose(fp);
+
+       return ret;
+}
+
 int mount_check(const char *path)
 {
        int ret = false;
index 23d058a..6c9f45f 100644 (file)
@@ -25,6 +25,7 @@
 
 int print_open_files(const char *mount_point);
 int terminate_process(const char *partition, bool force);
+bool is_in_use_partition(const char *partition);
 int mount_check(const char *path);
 int umount_partition(const char *path, const bool force);