dmsetup hangs forever

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>

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

 

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/dm-devel

[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux