Adapt device_open_excl to reusing of fds.

This commit is contained in:
Ondrej Kozina
2019-05-10 16:04:59 +02:00
committed by Milan Broz
parent 83c227d53c
commit 2d0079905e
3 changed files with 47 additions and 11 deletions

View File

@@ -123,6 +123,7 @@ int device_read_ahead(struct device *device, uint32_t *read_ahead);
int device_size(struct device *device, uint64_t *size);
int device_open(struct crypt_device *cd, struct device *device, int flags);
int device_open_excl(struct crypt_device *cd, struct device *device, int flags);
void device_release_excl(struct crypt_device *cd, struct device *device);
void device_disable_direct_io(struct device *device);
int device_is_identical(struct device *device1, struct device *device2);
int device_is_rotational(struct device *device);

View File

@@ -2304,11 +2304,12 @@ static int _reencrypt_init(struct crypt_device *cd,
log_err(cd, _("Data shift (%" PRIu64 " sectors) is less than future data offset (%" PRIu64 " sectors)."), params->data_shift, LUKS2_get_data_offset(hdr));
return -EINVAL;
}
/* FIXME: This is broken with current commit. Will get fixed with next one */
devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR);
if (devfd < 0) {
log_err(cd, _("Failed to open %s in exclusive mode (perhaps already mapped or mounted)."),
device_path(crypt_data_device(cd)));
if (devfd == -EBUSY)
log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd)));
else
log_err(cd,_("Failed to open %s in exclusive mode."), device_path(crypt_data_device(cd)));
return -EINVAL;
}
}
@@ -2348,6 +2349,7 @@ static int _reencrypt_init(struct crypt_device *cd,
} else
r = reencrypt_keyslot;
err:
device_release_excl(cd, crypt_data_device(cd));
if (r < 0)
crypt_load(cd, CRYPT_LUKS2, NULL);
@@ -2973,7 +2975,7 @@ static int _reencrypt_free(struct crypt_device *cd, struct luks2_hdr *hdr, struc
int crypt_reencrypt(struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
{
int r, excl_devfd = -1;
int r;
crypt_reencrypt_info ri;
struct luks2_hdr *hdr;
struct luks2_reenc_context *rh;
@@ -3008,10 +3010,8 @@ int crypt_reencrypt(struct crypt_device *cd,
} else {
if (crypt_storage_wrapper_get_type(rh->cw1) != DMCRYPT &&
crypt_storage_wrapper_get_type(rh->cw2) != DMCRYPT) {
/* FIXME: This is broken with current commit. Will get fixed with next one */
excl_devfd = device_open_excl(cd, crypt_data_device(cd), O_RDONLY);
if (excl_devfd < 0) {
log_err(cd, _("Failed to open device %s in exclusive mode. Already mounted?."), device_path(crypt_data_device(cd)));
if (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0) {
log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd)));
return -EBUSY;
}
}
@@ -3044,6 +3044,7 @@ int crypt_reencrypt(struct crypt_device *cd,
}
r = _reencrypt_free(cd, hdr, rh, rs, progress);
device_release_excl(cd, crypt_data_device(cd));
return r;
}

View File

@@ -48,6 +48,7 @@ struct device {
int ro_dev_fd;
int dev_fd;
int dev_fd_excl;
struct crypt_lock_handle *lh;
@@ -306,17 +307,44 @@ int device_open(struct crypt_device *cd, struct device *device, int flags)
int device_open_excl(struct crypt_device *cd, struct device *device, int flags)
{
const char *path;
struct stat st;
if (stat(device_path(device), &st))
if (!device)
return -EINVAL;
if (S_ISBLK(st.st_mode))
flags |= O_EXCL;
assert(!device_locked(device->lh));
if (device->dev_fd_excl < 0) {
path = device_path(device);
if (stat(path, &st))
return -EINVAL;
if (!S_ISBLK(st.st_mode))
log_dbg(cd, "%s is not a block device. Can't open in exclusive mode.",
path);
else {
device->dev_fd_excl = open(path, O_RDONLY | O_EXCL);
if (device->dev_fd_excl < 0)
return errno == EBUSY ? -EBUSY : device->dev_fd_excl;
log_dbg(cd, "Device %s is blocked for exclusive open.", path);
}
}
return device_open_internal(cd, device, flags);
}
void device_release_excl(struct crypt_device *cd, struct device *device)
{
if (device && device->dev_fd_excl >= 0) {
if (close(device->dev_fd_excl))
log_dbg(cd, "Failed to release exclusive handle on device %s.",
device_path(device));
else
log_dbg(cd, "Closed exclusive fd for %s.", device_path(device));
device->dev_fd_excl = -1;
}
}
int device_open_locked(struct crypt_device *cd, struct device *device, int flags)
{
assert(!crypt_metadata_locking_enabled() || device_locked(device->lh));
@@ -346,6 +374,7 @@ int device_alloc_no_check(struct device **device, const char *path)
dev->loop_fd = -1;
dev->ro_dev_fd = -1;
dev->dev_fd = -1;
dev->dev_fd_excl = -1;
dev->o_direct = 1;
*device = dev;
@@ -393,6 +422,11 @@ void device_free(struct crypt_device *cd, struct device *device)
close(device->dev_fd);
}
if (device->dev_fd_excl != -1) {
log_dbg(cd, "Closed exclusive fd for %s.", device_path(device));
close(device->dev_fd_excl);
}
if (device->loop_fd != -1) {
log_dbg(cd, "Closed loop %s (%s).", device->path, device->file_path);
close(device->loop_fd);