Fix bug in DM iteration and standardise how to iterate through DM layers (#40426)
get_block_device_harder_fd() currently only traverses one level of device mapper stacking when looking for the underlying block device. This causes issues with nested DM setups like dm-crypt on top of dm-integrity, where we don't traverse enough to get the actual physical device. Fix this by iterating through all DM layers until we reach a device with no underlying device. And while we're at it also make cgroups use the same logic. Fixes: #40419
This commit is contained in:
@@ -101,7 +101,7 @@ int block_device_get_whole_disk(sd_device *dev, sd_device **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int block_device_get_originating(sd_device *dev, sd_device **ret) {
|
||||
static int block_device_get_originating_one(sd_device *dev, sd_device **ret) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *first_found = NULL;
|
||||
const char *suffix;
|
||||
dev_t devnum = 0; /* avoid false maybe-uninitialized warning */
|
||||
@@ -148,6 +148,39 @@ int block_device_get_originating(sd_device *dev, sd_device **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int block_device_get_originating(sd_device *dev, sd_device **ret, bool recursive) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *current = NULL;
|
||||
int r;
|
||||
|
||||
assert(dev);
|
||||
assert(ret);
|
||||
|
||||
if (!recursive)
|
||||
return block_device_get_originating_one(dev, ret);
|
||||
|
||||
current = sd_device_ref(dev);
|
||||
|
||||
for (;;) {
|
||||
sd_device *origin;
|
||||
|
||||
r = block_device_get_originating_one(current, &origin);
|
||||
if (r == -ENOENT)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_device_unref(current);
|
||||
current = origin;
|
||||
}
|
||||
|
||||
if (current == dev)
|
||||
return -ENOENT;
|
||||
|
||||
*ret = TAKE_PTR(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int block_device_new_from_fd(int fd, BlockDeviceLookupFlags flags, sd_device **ret) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
dev_t devnum;
|
||||
@@ -172,7 +205,7 @@ int block_device_new_from_fd(int fd, BlockDeviceLookupFlags flags, sd_device **r
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = block_device_get_originating(dev_whole_disk, &dev_origin);
|
||||
r = block_device_get_originating(dev_whole_disk, &dev_origin, /* recursive= */ false);
|
||||
if (r >= 0)
|
||||
device_unref_and_replace(dev, dev_origin);
|
||||
else if (r != -ENOENT)
|
||||
@@ -290,7 +323,7 @@ int get_block_device(const char *path, dev_t *ret) {
|
||||
return get_block_device_fd(fd, ret);
|
||||
}
|
||||
|
||||
int block_get_originating(dev_t dt, dev_t *ret) {
|
||||
int block_get_originating(dev_t dt, dev_t *ret, bool recursive) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL, *origin = NULL;
|
||||
int r;
|
||||
|
||||
@@ -300,7 +333,7 @@ int block_get_originating(dev_t dt, dev_t *ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = block_device_get_originating(dev, &origin);
|
||||
r = block_device_get_originating(dev, &origin, recursive);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -313,14 +346,14 @@ int get_block_device_harder_fd(int fd, dev_t *ret) {
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
/* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its
|
||||
* immediate parent, if there is one. */
|
||||
/* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking
|
||||
* for its underlying physical device, if there is one. */
|
||||
|
||||
r = get_block_device_fd(fd, ret);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = block_get_originating(*ret, ret);
|
||||
r = block_get_originating(*ret, ret, /* recursive= */ true);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to chase block device, ignoring: %m");
|
||||
|
||||
|
||||
@@ -24,10 +24,9 @@ int block_device_new_from_path(const char *path, BlockDeviceLookupFlags flags, s
|
||||
|
||||
int block_device_is_whole_disk(sd_device *dev);
|
||||
int block_device_get_whole_disk(sd_device *dev, sd_device **ret);
|
||||
int block_device_get_originating(sd_device *dev, sd_device **ret);
|
||||
|
||||
int block_device_get_originating(sd_device *dev, sd_device **ret, bool recursive);
|
||||
int block_get_whole_disk(dev_t d, dev_t *ret);
|
||||
int block_get_originating(dev_t d, dev_t *ret);
|
||||
int block_get_originating(dev_t d, dev_t *ret, bool recursive);
|
||||
|
||||
int get_block_device_fd(int fd, dev_t *ret);
|
||||
int get_block_device(const char *path, dev_t *ret);
|
||||
|
||||
Reference in New Issue
Block a user