1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-18 10:04:20 +03:00

Retry DM_DEVICE_REMOVE ioctl if device is busy.

This is a workaround for long-lasting problem with using the WATCH udev
rule. When trying to remove a DM device, this one can still be opened
while processing the event in parallel (generated based on the WATCH
udev rule).

Let's use this until we have a proper solution.
This commit is contained in:
Peter Rajnoha 2011-09-13 15:13:41 +00:00
parent cc9dc919e6
commit 8171b93700
2 changed files with 16 additions and 0 deletions

View File

@ -1,5 +1,6 @@
Version 1.02.68 - Version 1.02.68 -
================================== ==================================
Retry DM_DEVICE_REMOVE ioctl if device is busy.
Remove unused passed parameters for _mirror_emit_segment_line(). Remove unused passed parameters for _mirror_emit_segment_line().
Add dm_config and string character escaping functions to libdevmapper. Add dm_config and string character escaping functions to libdevmapper.
Mark unreleased memory pools as internal error. Mark unreleased memory pools as internal error.

View File

@ -1539,11 +1539,14 @@ static const char *_sanitise_message(char *message)
return sanitised_message; return sanitised_message;
} }
#define DM_REMOVE_IOCTL_RETRIES 25
static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
unsigned repeat_count) unsigned repeat_count)
{ {
struct dm_ioctl *dmi; struct dm_ioctl *dmi;
int ioctl_with_uevent; int ioctl_with_uevent;
int retries = DM_REMOVE_IOCTL_RETRIES;
dmi = _flatten(dmt, repeat_count); dmi = _flatten(dmt, repeat_count);
if (!dmi) { if (!dmi) {
@ -1627,11 +1630,23 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmt->sector, _sanitise_message(dmt->message), dmt->sector, _sanitise_message(dmt->message),
dmi->data_size); dmi->data_size);
#ifdef DM_IOCTLS #ifdef DM_IOCTLS
repeat_dm_ioctl:
if (ioctl(_control_fd, command, dmi) < 0) { if (ioctl(_control_fd, command, dmi) < 0) {
if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) || if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
(dmt->type == DM_DEVICE_MKNODES) || (dmt->type == DM_DEVICE_MKNODES) ||
(dmt->type == DM_DEVICE_STATUS))) (dmt->type == DM_DEVICE_STATUS)))
dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */ dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */
/*
* FIXME: This is a workaround for asynchronous events generated
* as a result of using the WATCH udev rule with which we
* have no way of synchronizing. Processing such events in
* parallel causes devices to be open.
*/
else if (errno == EBUSY && (dmt->type == DM_DEVICE_REMOVE) && retries--) {
log_debug("device-mapper: device is busy, retrying removal");
usleep(200000);
goto repeat_dm_ioctl;
}
else { else {
if (_log_suppress) if (_log_suppress)
log_verbose("device-mapper: %s ioctl " log_verbose("device-mapper: %s ioctl "