dissect: account for EBUSY when verity device already exists

In some cases, libdevmapper/libcrypsetup might return EBUSY instead of
EEXIST when opening a shared device. Treat it in the same way.
This commit is contained in:
Luca Boccassi 2020-08-10 11:15:48 +01:00
parent c419b6f0cf
commit 9ecb5c10fd
1 changed files with 14 additions and 7 deletions

View File

@ -1430,26 +1430,33 @@ static int verity_partition(
* Improvements in libcrypsetup can ensure this never happens: https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r, 0, -EEXIST, -ENODEV))
if (!IN_SET(r,
0, /* Success */
-EEXIST, /* Volume is already open and ready to be used */
-EBUSY, /* Volume is being opened but not ready, crypt_init_by_name can fetch details */
-ENODEV /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */))
return r;
if (r == -EEXIST) {
if (IN_SET(r, -EEXIST, -EBUSY)) {
struct crypt_device *existing_cd = NULL;
if (!restore_deferred_remove){
/* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */
r = dm_deferred_remove_cancel(name);
if (r < 0)
/* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */
if (r < 0 && r != -ENXIO)
return log_debug_errno(r, "Disabling automated deferred removal for verity device %s failed: %m", node);
restore_deferred_remove = strdup(name);
if (!restore_deferred_remove)
return -ENOMEM;
if (r == 0) {
restore_deferred_remove = strdup(name);
if (!restore_deferred_remove)
return -ENOMEM;
}
}
r = verity_can_reuse(root_hash, root_hash_size, !!root_hash_sig || !!hash_sig_from_file, name, &existing_cd);
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r, 0, -ENODEV, -ENOENT))
if (!IN_SET(r, 0, -ENODEV, -ENOENT, -EBUSY))
return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node);
if (r == 0) {
/* devmapper might say that the device exists, but the devlink might not yet have been