libdevmapper: always return EEXIST if a task fails because the device already exists

Allows concurrent opens to return a usable error instead of EINVAL
This commit is contained in:
Milan Broz
2020-08-08 20:54:07 +01:00
committed by Luca Boccassi
parent cb183de1da
commit 31ebf3dc2c
2 changed files with 23 additions and 8 deletions

View File

@@ -1305,6 +1305,12 @@ err:
return r;
}
static bool dm_device_exists(struct crypt_device *cd, const char *name)
{
int r = dm_status_device(cd, name);
return (r >= 0 || r == -EEXIST);
}
static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
const char *uuid, struct crypt_dm_active_device *dmd)
{
@@ -1354,8 +1360,11 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (!dm_task_run(dmt))
if (!dm_task_run(dmt)) {
if (dm_device_exists(cd, name))
r = -EEXIST;
goto out;
}
if (dm_task_get_info(dmt, &dmi))
r = 0;
@@ -1720,6 +1729,7 @@ static int dm_status_dmi(const char *name, struct dm_info *dmi,
goto out;
}
r = -EEXIST;
dm_get_next_target(dmt, NULL, &start, &length,
&target_type, &params);

View File

@@ -4161,21 +4161,26 @@ static int _activate_loopaes(struct crypt_device *cd,
static int _activate_check_status(struct crypt_device *cd, const char *name, unsigned reload)
{
crypt_status_info ci;
int r;
if (!name)
return 0;
ci = crypt_status(cd, name);
if (ci == CRYPT_INVALID) {
log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name);
return -EINVAL;
} else if (ci >= CRYPT_ACTIVE && !reload) {
r = dm_status_device(cd, name);
if (r >= 0 && reload)
return 0;
if (r >= 0 || r == -EEXIST) {
log_err(cd, _("Device %s already exists."), name);
return -EEXIST;
}
return 0;
if (r == -ENODEV)
return 0;
log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name);
return r;
}
// activation/deactivation of device mapping