From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peter Rajnoha Date: Tue, 13 Sep 2011 16:31:52 +0200 Subject: [PATCH] Retry dm device removal if busy Message-ID: <4E6F6958.5020609@redhat.com> List-Id: To: lvm-devel@redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit If a dm device is being opened in parallel while we're trying to remove it, we'll end up with an error that the device is busy. This is a legitimate error, but with udev in play and asynchronous events generated as a result of using the WATCH udev rule, we can get into a situation where such failure is very unpleasant. Let's try the removal a few times then. Though this is not a complete solution to the problem, let's use this until we have one. Peter --- libdm/ioctl/libdm-iface.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index 816f1e6..e4a3a1f 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -1539,11 +1539,14 @@ static const char *_sanitise_message(char *message) return sanitised_message; } +#define DM_REMOVE_IOCTL_RETRIES 5 + static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, unsigned repeat_count) { struct dm_ioctl *dmi; int ioctl_with_uevent; + int retries = DM_REMOVE_IOCTL_RETRIES; dmi = _flatten(dmt, repeat_count); 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), dmi->data_size); #ifdef DM_IOCTLS +repeat_dm_ioctl: if (ioctl(_control_fd, command, dmi) < 0) { if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) || (dmt->type == DM_DEVICE_MKNODES) || (dmt->type == DM_DEVICE_STATUS))) 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"); + sleep(1); + goto repeat_dm_ioctl; + } else { if (_log_suppress) log_verbose("device-mapper: %s ioctl "