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