}
/* If this is a LUKS/DM device, recursively try to get the originating block device */
- while (block_get_originating(*ret, ret) >= 0)
- ;
+ (void) block_get_originating(*ret, ret, /* recursive= */ true);
/* If this is a partition, try to get the originating block device */
(void) block_get_whole_disk(*ret, ret);
return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Block device backing /var/ is not a LUKS2 device.");
_cleanup_(sd_device_unrefp) sd_device *origin = NULL;
- r = block_device_get_originating(dev, &origin);
+ r = block_device_get_originating(dev, &origin, /* recursive= */ false);
if (r < 0)
return log_error_errno(r, "Failed to get originating device of LUKS2 device backing /var/: %m");
return -ENOTBLK;
/* From dm-crypt to backing partition */
- r = block_get_originating(devno, &devno);
+ r = block_get_originating(devno, &devno, /* recursive= */ false);
if (r == -ENOENT)
log_debug_errno(r, "Device '%s' has no dm-crypt/dm-verity device, no need to look for underlying block device.", p);
else if (r < 0)
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 */
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;
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)
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;
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;
if (r <= 0)
return r;
- r = block_get_originating(*ret, ret);
+ r = block_get_originating(*ret, ret, /* recursive= */ false);
if (r < 0)
log_debug_errno(r, "Failed to chase block device, ignoring: %m");
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);
assert(device);
- r = block_device_get_originating(device, &origin);
+ r = block_device_get_originating(device, &origin, /* recursive= */ false);
if (r < 0 && r != -ENOENT)
return r;
if (r >= 0)
(void) sd_device_get_devname(d, &devname);
_cleanup_(sd_device_unrefp) sd_device *d_originating = NULL;
- r = block_device_get_originating(d, &d_originating);
+ r = block_device_get_originating(d, &d_originating, /* recursive= */ false);
if (r < 0 && r != -ENOENT)
log_device_debug_errno(d, r, "Failed to get originating device for '%s', ignoring: %m", strna(devname));
return 0;
}
- (void) block_get_originating(*ret, ret);
+ (void) block_get_originating(*ret, ret, /* recursive= */ false);
return 1;
}