[PATCH] discover/devmapper: Retry dm-device remove if busy
Samuel Mendoza-Jonas
sam at mendozajonas.com
Thu Dec 13 11:51:16 AEDT 2018
On Tue, 2018-12-04 at 13:34 +1100, Samuel Mendoza-Jonas wrote:
> Buildroot's libdm is not built with --enable-udev_sync, so device-mapper
> actions are not able to sync or wait for udev events.
> (see 185676316, "discover/devmapper: Disable libdm udev sync support")
>
> This can cause an issue when tearing down a snapshot in
> devmapper_destroy_snapshot() which performs a DM_DEVICE_REMOVE task
> against the snapshot, origin, and base devices one after the other. In
> some cases if the interval between these actions is too short the action
> can fail as the preceding device hasn't disappeared yet and the device
> being removed is still busy.
>
> Since we don't yet have a way to tell exactly when the device is ready,
> pause for a short time and retry the action, letting
> devmapper_destroy_snapshot() continue and, for example, letting
> mount_device() fall back to the physical device.
>
> Signed-off-by: Samuel Mendoza-Jonas <sam at mendozajonas.com>
Merged as 89cde533
> ---
> In the future we'll enable udev_sync in Buildroot but this should help
> us fallback properly on existing systems. Using usleep() isn't perfect,
> however it's similar to what existing lvm tools & libraries do in the
> same situation, and allows us to fall back to the physical device
> quickly.
>
> discover/devmapper.c | 24 +++++++++++++++++++-----
> 1 file changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/discover/devmapper.c b/discover/devmapper.c
> index f7407b77..0a4d320e 100644
> --- a/discover/devmapper.c
> +++ b/discover/devmapper.c
> @@ -457,24 +457,32 @@ static int destroy_device(const char *dm_name)
> {
> struct dm_task *task;
> uint32_t cookie;
> - int rc = -1;
> + int rc, retries = 0;
>
> +retry:
> task = dm_task_create(DM_DEVICE_REMOVE);
> if (!task) {
> - pb_log_fn("could not create dm_task\n");
> + pb_debug_fn("could not create dm_task\n");
> return -1;
> }
>
> if (!dm_task_set_name(task, dm_name)) {
> - pb_log("No dm device named '%s'\n", dm_name);
> + rc = dm_task_get_errno(task);
> + pb_debug_fn("Couldn't set name for %s, %s (%d)\n",
> + dm_name, strerror(rc), rc);
> goto out;
> }
>
> - if (!set_cookie(task, &cookie))
> + if (!set_cookie(task, &cookie)) {
> + rc = dm_task_get_errno(task);
> + pb_debug_fn("set_cookie failed, %s (%d)\n", strerror(rc), rc);
> goto out;
> + }
>
> if (!dm_task_run(task)) {
> - pb_log("Unable to remove device '%s'\n", dm_name);
> + rc = dm_task_get_errno(task);
> + pb_debug_fn("Unable to remove device '%s', %s (%d)\n",
> + dm_name, strerror(rc), rc);
> goto out;
> }
>
> @@ -485,6 +493,12 @@ static int destroy_device(const char *dm_name)
>
> out:
> dm_task_destroy(task);
> + if (rc == EBUSY && retries < 5) {
> + pb_log_fn("Device busy, retry %d..\n", retries);
> + usleep(100000);
> + retries++;
> + goto retry;
> + }
> return rc;
> }
>
More information about the Petitboot
mailing list