[dm-devel] dmsetup hangs forever

Zhangyanfei (YF) yanfei.zhang at huawei.com
Thu Oct 26 08:07:01 UTC 2017


Hello

I find an issue when use  dmsetup in the situation udev event timeout.

Dmsetup use the dm_udev_wait function sync with udev event.When use the dmsetup generate a new dm-disk, if the raw disk is abnormal(for example ,a ipsan disk hung IO request), the udevd daemon handle the dm-disk udev event maybe timeout, and will not notify the dmsetup  by semaphore. And because the  dm_udev_wait use the semop to sync with udevd, if udevd event timeout, the dmsetup will hung forever even when the raw disk be recovery.

I wonder if we could use the semtimedop instead semop to add the timeout in function  dm_udev_wait. If the udevd daemon timeout when handle the dm event, the dm_udev_wait could timeout too, and the dmsetup could return error.

This is my patch base lvm2-2.02.115-3:

>From 6961f824abe8eb15f8328f2f4bd39f4cdbf65d4f Mon Sep 17 00:00:00 2001
From: fengtiantian <fengtiantian at huawei.com<mailto:fengtiantian at huawei.com>>
Date: Mon, 23 Oct 2017 19:29:55 +0800
Subject: [PATCH] add timeout when fail to wait udev

---
libdm/libdm-common.c |  7 ++++++-
tools/dmsetup.c      | 20 ++++++++++++++++----
2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index bd51645..ede2fea 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -59,6 +59,8 @@ union semun
#endif
#endif

+#define UDEV_SEM_TIMEOUT 300
+
static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
static char _sysfs_dir[PATH_MAX] = "/sys/";
static char _path0[PATH_MAX];           /* path buffer, safe 4kB on stack */
@@ -2476,6 +2478,9 @@ static int _udev_wait(uint32_t cookie)
{
        int semid;
        struct sembuf sb = {0, 0, 0};
+       struct timespec timeout;
+       timeout.tv_sec = UDEV_SEM_TIMEOUT;
+       timeout.tv_nsec = 0;

        if (!cookie || !dm_udev_get_sync_support())
                return 1;
@@ -2496,7 +2501,7 @@ static int _udev_wait(uint32_t cookie)
                             cookie, semid);

repeat_wait:
-       if (semop(semid, &sb, 1) < 0) {
+       if (semtimedop(semid, &sb, 1,&timeout) < 0) {
                if (errno == EINTR)
                        goto repeat_wait;
                else if (errno == EIDRM)
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index 4202dbb..0840031 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -619,6 +619,7 @@ static int _load(CMD_ARGS)
static int _create(CMD_ARGS)
{
        int r = 0;
+       int udev_wait_r = 1;
        struct dm_task *dmt;
        const char *file = NULL;
        uint32_t cookie = 0;
@@ -695,18 +696,22 @@ static int _create(CMD_ARGS)

       out:
        if (!_udev_cookie)
-               (void) dm_udev_wait(cookie);
+               udev_wait_r = dm_udev_wait(cookie);

        if (r && _switches[VERBOSE_ARG])
                r = _display_info(dmt);

        dm_task_destroy(dmt);

+       if(!udev_wait_r)
+               return 0;
+
        return r;
}
static int _do_rename(const char *name, const char *new_name, const char *new_uuid) {
        int r = 0;
+       int udev_wait_r = 1;
        struct dm_task *dmt;
        uint32_t cookie = 0;
        uint16_t udev_flags = 0;
@@ -751,10 +756,13 @@ static int _do_rename(const char *name, const char *new_name, const char *new_uu

       out:
        if (!_udev_cookie)
-               (void) dm_udev_wait(cookie);
+               udev_wait_r =  dm_udev_wait(cookie);

        dm_task_destroy(dmt);

+       if (!udev_wait_r)
+               return 0;
+
        return r;
}

@@ -1267,7 +1275,8 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
        int udev_wait_flag = task == DM_DEVICE_RESUME ||
                             task == DM_DEVICE_REMOVE;
        int r = 0;
-
+       int udev_wait_r = 1;
+
        struct dm_task *dmt;

        if (!(dmt = dm_task_create(task)))
@@ -1326,13 +1335,16 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)

       out:
        if (!_udev_cookie && udev_wait_flag)
-               (void) dm_udev_wait(cookie);
+               udev_wait_r = dm_udev_wait(cookie);

        if (r && display && _switches[VERBOSE_ARG])
                r = _display_info(dmt);

        dm_task_destroy(dmt);

+       if(!udev_wait_r)
+               return 0;
+
        return r;
}

--
1.8.3.1

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/dm-devel/attachments/20171026/fc33d99b/attachment.htm>


More information about the dm-devel mailing list