mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-30 17:18:21 +03:00
libdm: Add dm_task_get_errno to return ioctl errno.
There are reports of unexplained ioctl failures when using dmeventd. An explanation might be that the wrong value of errno is being used. Change libdevmapper to store an errno set by from dm ioctl() directly and provide it to the caller through a new dm_task_get_errno() function. [Replaced f9510548667754d9209b232348ccd2d806c0f1d8]
This commit is contained in:
parent
b244fffc18
commit
eeb498627c
@ -1,5 +1,7 @@
|
||||
Version 1.02.98 -
|
||||
===============================
|
||||
Add dm_task_get_errno() to return any unexpected errno from a dm ioctl call.
|
||||
Use copy of errno made after each dm ioctl call in case errno changes later.
|
||||
|
||||
Version 1.02.97 - 15th May 2015
|
||||
===============================
|
||||
|
@ -710,6 +710,7 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
|
||||
int ret = DM_WAIT_RETRY;
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
int ioctl_errno;
|
||||
|
||||
*task = 0;
|
||||
|
||||
@ -739,27 +740,29 @@ static int _event_wait(struct thread_status *thread, struct dm_task **task)
|
||||
* either for a timeout event, or to cancel the thread.
|
||||
*/
|
||||
set = _unblock_sigalrm();
|
||||
errno = 0;
|
||||
if (dm_task_run(dmt)) {
|
||||
thread->current_events |= DM_EVENT_DEVICE_ERROR;
|
||||
ret = DM_WAIT_INTR;
|
||||
|
||||
if ((ret = dm_task_get_info(dmt, &info)))
|
||||
thread->event_nr = info.event_nr;
|
||||
} else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) {
|
||||
} else {
|
||||
ioctl_errno = dm_task_get_errno(dmt);
|
||||
if (thread->events & DM_EVENT_TIMEOUT && ioctl_errno == EINTR) {
|
||||
thread->current_events |= DM_EVENT_TIMEOUT;
|
||||
ret = DM_WAIT_INTR;
|
||||
} else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) {
|
||||
} else if (thread->status == DM_THREAD_SHUTDOWN && ioctl_errno == EINTR)
|
||||
ret = DM_WAIT_FATAL;
|
||||
} else {
|
||||
else {
|
||||
syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s",
|
||||
errno, strerror(errno));
|
||||
if (errno == ENXIO) {
|
||||
ioctl_errno, strerror(ioctl_errno));
|
||||
if (ioctl_errno == ENXIO) {
|
||||
syslog(LOG_ERR, "%s disappeared, detaching",
|
||||
thread->device.name);
|
||||
ret = DM_WAIT_FATAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUGLOG("Completed waitevent task for %s", thread->device.uuid);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &set, NULL);
|
||||
|
1
libdm/.exported_symbols.DM_1_02_98
Normal file
1
libdm/.exported_symbols.DM_1_02_98
Normal file
@ -0,0 +1 @@
|
||||
dm_task_get_errno
|
@ -1717,6 +1717,8 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
struct dm_ioctl *dmi;
|
||||
int ioctl_with_uevent;
|
||||
|
||||
dmt->ioctl_errno = 0;
|
||||
|
||||
dmi = _flatten(dmt, buffer_repeat_count);
|
||||
if (!dmi) {
|
||||
log_error("Couldn't create ioctl argument.");
|
||||
@ -1803,12 +1805,13 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
#ifdef DM_IOCTLS
|
||||
if (ioctl(_control_fd, command, dmi) < 0 &&
|
||||
dmt->expected_errno != errno) {
|
||||
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
dmt->ioctl_errno = errno;
|
||||
if (dmt->ioctl_errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
|
||||
(dmt->type == DM_DEVICE_MKNODES) ||
|
||||
(dmt->type == DM_DEVICE_STATUS)))
|
||||
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
|
||||
else {
|
||||
if (_log_suppress || errno == EINTR)
|
||||
if (_log_suppress || dmt->ioctl_errno == EINTR)
|
||||
log_verbose("device-mapper: %s ioctl on %s%s%s%.0d%s%.0d%s%s "
|
||||
"failed: %s",
|
||||
_cmd_data_v4[dmt->type].name,
|
||||
@ -1819,7 +1822,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
dmt->minor > 0 ? dmt->minor : 0,
|
||||
dmt->major > 0 && dmt->minor == 0 ? "0" : "",
|
||||
dmt->major > 0 ? ")" : "",
|
||||
strerror(errno));
|
||||
strerror(dmt->ioctl_errno));
|
||||
else
|
||||
log_error("device-mapper: %s ioctl on %s%s%s%.0d%s%.0d%s%s "
|
||||
"failed: %s",
|
||||
@ -1831,14 +1834,14 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
dmt->minor > 0 ? dmt->minor : 0,
|
||||
dmt->major > 0 && dmt->minor == 0 ? "0" : "",
|
||||
dmt->major > 0 ? ")" : "",
|
||||
strerror(errno));
|
||||
strerror(dmt->ioctl_errno));
|
||||
|
||||
/*
|
||||
* It's sometimes worth retrying after EBUSY in case
|
||||
* it's a transient failure caused by an asynchronous
|
||||
* process quickly scanning the device.
|
||||
*/
|
||||
*retryable = errno == EBUSY;
|
||||
*retryable = dmt->ioctl_errno == EBUSY;
|
||||
|
||||
goto error;
|
||||
}
|
||||
@ -1876,6 +1879,11 @@ void dm_task_update_nodes(void)
|
||||
#define DM_IOCTL_RETRIES 25
|
||||
#define DM_RETRY_USLEEP_DELAY 200000
|
||||
|
||||
int dm_task_get_errno(struct dm_task *dmt)
|
||||
{
|
||||
return dmt->ioctl_errno;
|
||||
}
|
||||
|
||||
int dm_task_run(struct dm_task *dmt)
|
||||
{
|
||||
struct dm_ioctl *dmi;
|
||||
|
@ -68,6 +68,7 @@ struct dm_task {
|
||||
int deferred_remove;
|
||||
int enable_checks;
|
||||
int expected_errno;
|
||||
int ioctl_errno;
|
||||
|
||||
char *uuid;
|
||||
char *mangled_uuid;
|
||||
|
@ -392,6 +392,11 @@ int dm_get_status_thin(struct dm_pool *mem, const char *params,
|
||||
*/
|
||||
int dm_task_run(struct dm_task *dmt);
|
||||
|
||||
/*
|
||||
* The errno from the last device-mapper ioctl performed by dm_task_run.
|
||||
*/
|
||||
int dm_task_get_errno(struct dm_task *dmt);
|
||||
|
||||
/*
|
||||
* Call this to make or remove the device nodes associated with previously
|
||||
* issued commands.
|
||||
|
Loading…
Reference in New Issue
Block a user