Fix detection of direct-io with suspended devices.

Currently, direct-io is disabled if underlying device is suspended.

This was an unfortunate change, as it is part of data corruption
problem in online reenryption.

Let's relax the test to assume that suspended device
(suspended =>  must be a device-mapper device) supports direct-io.

The read test is still needed as some network based devices
misbehaves if opened with direct-io flag.
This commit is contained in:
Milan Broz
2024-08-27 12:13:54 +02:00
parent e4d25d18eb
commit 4cdd022ba4

View File

@@ -127,11 +127,19 @@ static size_t device_alignment_fd(int devfd)
return (size_t)alignment; return (size_t)alignment;
} }
static int device_read_test(int devfd) static int device_read_test(struct crypt_device *cd, int devfd, struct device *device)
{ {
char buffer[512]; char buffer[512];
int r = -EIO; int r = -EIO;
size_t minsize = 0, blocksize, alignment; size_t minsize = 0, blocksize, alignment;
const char *dm_name;
/* skip check for suspended DM devices */
dm_name = device_dm_name(device);
if (dm_name && dm_status_suspended(cd, dm_name) > 0) {
log_dbg(cd, "Device %s is suspended, assuming direct-io is supported.", dm_name);
return 0;
}
blocksize = device_block_size_fd(devfd, &minsize); blocksize = device_block_size_fd(devfd, &minsize);
alignment = device_alignment_fd(devfd); alignment = device_alignment_fd(devfd);
@@ -148,6 +156,8 @@ static int device_read_test(int devfd)
if (read_blockwise(devfd, blocksize, alignment, buffer, minsize) == (ssize_t)minsize) if (read_blockwise(devfd, blocksize, alignment, buffer, minsize) == (ssize_t)minsize)
r = 0; r = 0;
log_dbg(cd, "Direct-io is supported and works.");
crypt_safe_memzero(buffer, sizeof(buffer)); crypt_safe_memzero(buffer, sizeof(buffer));
return r; return r;
} }
@@ -165,7 +175,6 @@ static int device_ready(struct crypt_device *cd, struct device *device)
int devfd = -1, r = 0; int devfd = -1, r = 0;
struct stat st; struct stat st;
size_t tmp_size; size_t tmp_size;
const char *dm_name;
if (!device) if (!device)
return -EINVAL; return -EINVAL;
@@ -176,12 +185,7 @@ static int device_ready(struct crypt_device *cd, struct device *device)
device->o_direct = 0; device->o_direct = 0;
devfd = open(device_path(device), O_RDONLY | O_DIRECT); devfd = open(device_path(device), O_RDONLY | O_DIRECT);
if (devfd >= 0) { if (devfd >= 0) {
/* skip check for suspended DM devices */ if (device_read_test(cd, devfd, device) == 0) {
dm_name = device_dm_name(device);
if (dm_name && dm_status_suspended(cd, dm_name) > 0) {
close(devfd);
devfd = -1;
} else if (device_read_test(devfd) == 0) {
device->o_direct = 1; device->o_direct = 1;
} else { } else {
close(devfd); close(devfd);