Zhangyanfei (YF)
2017-10-26 08:07:01 UTC
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.
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
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.
From 6961f824abe8eb15f8328f2f4bd39f4cdbf65d4f Mon Sep 17 00:00:00 2001
From: fengtiantian <***@huawei.com<mailto:***@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