Merge pull request #30467 from poettering/loop-block-tweaks

various tweaks to block device ioctls, and loop device mgmt
This commit is contained in:
Daan De Meyer
2023-12-14 09:38:17 +01:00
committed by GitHub
11 changed files with 91 additions and 37 deletions

View File

@@ -827,16 +827,15 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
pager_open(arg_pager_flags);
if (arg_json_format_flags & JSON_FORMAT_OFF)
printf(" Name: %s%s%s\n", ansi_highlight(), bn, ansi_normal());
if (ioctl(d->fd, BLKGETSIZE64, &size) < 0)
log_debug_errno(errno, "Failed to query size of loopback device: %m");
else if (arg_json_format_flags & JSON_FORMAT_OFF)
printf(" Size: %s\n", FORMAT_BYTES(size));
if (arg_json_format_flags & JSON_FORMAT_OFF) {
printf(" Sec. Size: %" PRIu32 "\n", m->sector_size);
printf(" Name: %s%s%s\n",
ansi_highlight(), bn, ansi_normal());
printf(" Size: %s\n",
FORMAT_BYTES(m->image_size));
printf(" Sec. Size: %" PRIu32 "\n",
m->sector_size);
printf(" Arch.: %s\n",
strna(architecture_to_string(dissected_image_architecture(m))));
@@ -962,6 +961,11 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
table_set_ersatz_string(t, TABLE_ERSATZ_DASH);
(void) table_set_align_percent(t, table_get_cell(t, 0, 9), 100);
/* Hide the device path if this is a loopback device that is not relinquished, since that means the
* device node is not going to be useful the instant our command exits */
if ((!d || d->created) && (arg_json_format_flags & JSON_FORMAT_OFF))
table_hide_column_from_display(t, 8);
for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) {
DissectedPartition *p = m->partitions + i;

View File

@@ -199,7 +199,7 @@ static int block_get_size_by_fd(int fd, uint64_t *ret) {
if (!S_ISBLK(st.st_mode))
return -ENOTBLK;
return RET_NERRNO(ioctl(fd, BLKGETSIZE64, ret));
return blockdev_get_device_size(fd, ret);
}
static int block_get_size_by_path(const char *path, uint64_t *ret) {
@@ -1295,9 +1295,6 @@ int home_setup_luks(
if (!IN_SET(errno, ENOTTY, EINVAL))
return log_error_errno(errno, "Failed to get block device metrics of %s: %m", n);
if (ioctl(setup->loop->fd, BLKGETSIZE64, &size) < 0)
return log_error_errno(r, "Failed to read block device size of %s: %m", n);
if (fstat(setup->loop->fd, &st) < 0)
return log_error_errno(r, "Failed to stat block device %s: %m", n);
assert(S_ISBLK(st.st_mode));
@@ -1329,6 +1326,8 @@ int home_setup_luks(
offset *= 512U;
}
size = setup->loop->device_size;
} else {
#if HAVE_VALGRIND_MEMCHECK_H
VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
@@ -2227,8 +2226,9 @@ int home_create_luks(
if (flock(setup->image_fd, LOCK_EX) < 0) /* make sure udev doesn't read from it while we operate on the device */
return log_error_errno(errno, "Failed to lock block device %s: %m", ip);
if (ioctl(setup->image_fd, BLKGETSIZE64, &block_device_size) < 0)
return log_error_errno(errno, "Failed to read block device size: %m");
r = blockdev_get_device_size(setup->image_fd, &block_device_size);
if (r < 0)
return log_error_errno(r, "Failed to read block device size: %m");
if (h->disk_size == UINT64_MAX) {
@@ -3183,8 +3183,9 @@ int home_resize_luks(
} else
log_info("Operating on whole block device %s.", ip);
if (ioctl(image_fd, BLKGETSIZE64, &old_image_size) < 0)
return log_error_errno(errno, "Failed to determine size of original block device: %m");
r = blockdev_get_device_size(image_fd, &old_image_size);
if (r < 0)
return log_error_errno(r, "Failed to determine size of original block device: %m");
if (flock(image_fd, LOCK_EX) < 0) /* make sure udev doesn't read from it while we operate on the device */
return log_error_errno(errno, "Failed to lock block device %s: %m", ip);

View File

@@ -55,8 +55,9 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_
return log_error_errno(r, "Failed to open main block device " DEVNUM_FORMAT_STR ": %m",
DEVNUM_FORMAT_VAL(main_devno));
if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0)
return log_error_errno(errno, "Failed to query size of \"%s\" (before resize): %m",
r = blockdev_get_device_size(main_devfd, &size);
if (r < 0)
return log_error_errno(r, "Failed to query size of \"%s\" (before resize): %m",
main_devpath);
log_debug("%s is %"PRIu64" bytes", main_devpath, size);
@@ -83,9 +84,9 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_
if (r < 0)
return log_error_errno(r, "crypt_resize() of %s failed: %m", devpath);
if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0)
log_warning_errno(errno, "Failed to query size of \"%s\" (after resize): %m",
devpath);
r = blockdev_get_device_size(main_devfd, &size);
if (r < 0)
log_warning_errno(r, "Failed to query size of \"%s\" (after resize): %m", devpath);
else
log_debug("%s is now %"PRIu64" bytes", main_devpath, size);
@@ -250,8 +251,9 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to open block device " DEVNUM_FORMAT_STR ": %m",
DEVNUM_FORMAT_VAL(devno));
if (ioctl(devfd, BLKGETSIZE64, &size) != 0)
return log_error_errno(errno, "Failed to query size of \"%s\": %m", devpath);
r = blockdev_get_device_size(devfd, &size);
if (r < 0)
return log_error_errno(r, "Failed to query size of \"%s\": %m", devpath);
log_debug("Resizing \"%s\" to %"PRIu64" bytes...", arg_target, size);

View File

@@ -6042,8 +6042,9 @@ static int context_open_copy_block_paths(
if (S_ISREG(st.st_mode))
size = st.st_size;
else if (S_ISBLK(st.st_mode)) {
if (ioctl(source_fd, BLKGETSIZE64, &size) != 0)
return log_error_errno(errno, "Failed to determine size of block device to copy from: %m");
r = blockdev_get_device_size(source_fd, &size);
if (r < 0)
return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
} else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing: %m", opened);
@@ -7365,8 +7366,9 @@ static int resize_backing_fd(
assert(loop_device);
if (ioctl(*fd, BLKGETSIZE64, &current_size) < 0)
return log_error_errno(errno, "Failed to determine size of block device %s: %m", node);
r = blockdev_get_device_size(*fd, &current_size);
if (r < 0)
return log_error_errno(r, "Failed to determine size of block device %s: %m", node);
} else {
r = stat_verify_regular(&st);
if (r < 0)

View File

@@ -777,6 +777,21 @@ int blockdev_get_sector_size(int fd, uint32_t *ret) {
return 0;
}
int blockdev_get_device_size(int fd, uint64_t *ret) {
uint64_t sz = 0;
assert(fd >= 0);
assert(ret);
/* This is just a type-safe wrapper around BLKGETSIZE64 that gets us around having to include messy linux/fs.h in various clients */
if (ioctl(fd, BLKGETSIZE64, &sz) < 0)
return -errno;
*ret = sz;
return 0;
}
int blockdev_get_root(int level, dev_t *ret) {
_cleanup_free_ char *p = NULL;
dev_t devno;

View File

@@ -57,5 +57,6 @@ int block_device_has_partitions(sd_device *dev);
int blockdev_reread_partition_table(sd_device *dev);
int blockdev_get_sector_size(int fd, uint32_t *ret);
int blockdev_get_device_size(int fd, uint64_t *ret);
int blockdev_get_root(int level, dev_t *ret);

View File

@@ -13,6 +13,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "chase.h"
#include "chattr-util.h"
@@ -446,8 +447,9 @@ static int image_make(
read_only = true;
}
if (ioctl(block_fd, BLKGETSIZE64, &size) < 0)
log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path ?: strnull(parent), filename);
r = blockdev_get_device_size(block_fd, &size);
if (r < 0)
log_debug_errno(r, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path ?: strnull(parent), filename);
block_fd = safe_close(block_fd);
}

View File

@@ -1547,6 +1547,7 @@ int dissect_image_file(
#if HAVE_BLKID
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_close_ int fd = -EBADF;
struct stat st;
int r;
assert(path);
@@ -1555,7 +1556,10 @@ int dissect_image_file(
if (fd < 0)
return -errno;
r = fd_verify_regular(fd);
if (fstat(fd, &st) < 0)
return -errno;
r = stat_verify_regular(&st);
if (r < 0)
return r;
@@ -1563,6 +1567,8 @@ int dissect_image_file(
if (r < 0)
return r;
m->image_size = st.st_size;
r = probe_sector_size(fd, &m->sector_size);
if (r < 0)
return r;
@@ -1759,8 +1765,9 @@ static int fs_grow(const char *node_path, int mount_fd, const char *mount_path)
if (node_fd < 0)
return log_debug_errno(errno, "Failed to open node device %s: %m", node_path);
if (ioctl(node_fd, BLKGETSIZE64, &size) != 0)
return log_debug_errno(errno, "Failed to get block device size of %s: %m", node_path);
r = blockdev_get_device_size(node_fd, &size);
if (r < 0)
return log_debug_errno(r, "Failed to get block device size of %s: %m", node_path);
if (mount_fd < 0) {
assert(mount_path);
@@ -3698,6 +3705,7 @@ int dissect_loop_device(
return r;
m->loop = loop_device_ref(loop);
m->image_size = m->loop->device_size;
m->sector_size = m->loop->sector_size;
r = dissect_image(m, loop->fd, loop->node, verity, mount_options, image_policy, flags);

View File

@@ -102,6 +102,7 @@ struct DissectedImage {
DecryptedImage *decrypted_image;
uint32_t sector_size;
uint64_t image_size;
char *image_name;
sd_id128_t image_uuid;

View File

@@ -149,8 +149,9 @@ static int loop_configure_verify(int fd, const struct loop_config *c) {
* effect hence. And if not use classic LOOP_SET_STATUS64. */
uint64_t z;
if (ioctl(fd, BLKGETSIZE64, &z) < 0)
return -errno;
r = blockdev_get_device_size(fd, &z);
if (r < 0)
return r;
if (z != c->info.lo_sizelimit) {
log_debug("LOOP_CONFIGURE is broken, doesn't honour .info.lo_sizelimit. Falling back to LOOP_SET_STATUS64.");
@@ -404,6 +405,11 @@ static int loop_configure(
assert_not_reached();
}
uint64_t device_size;
r = blockdev_get_device_size(loop_with_fd, &device_size);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get loopback device size: %m");
LoopDevice *d = new(LoopDevice, 1);
if (!d)
return log_oom_debug();
@@ -420,6 +426,8 @@ static int loop_configure(
.uevent_seqnum_not_before = seqnum,
.timestamp_not_before = timestamp,
.sector_size = c->block_size,
.device_size = device_size,
.created = true,
};
*ret = TAKE_PTR(d);
@@ -944,6 +952,11 @@ int loop_device_open(
if (r < 0)
return r;
uint64_t device_size;
r = blockdev_get_device_size(fd, &device_size);
if (r < 0)
return r;
r = sd_device_get_devnum(dev, &devnum);
if (r < 0)
return r;
@@ -976,6 +989,8 @@ int loop_device_open(
.uevent_seqnum_not_before = UINT64_MAX,
.timestamp_not_before = USEC_INFINITY,
.sector_size = sector_size,
.device_size = device_size,
.created = false,
};
*ret = d;
@@ -1057,8 +1072,9 @@ static int resize_partition(int partition_fd, uint64_t offset, uint64_t size) {
return -EINVAL;
current_offset *= 512U;
if (ioctl(partition_fd, BLKGETSIZE64, &current_size) < 0)
return -EINVAL;
r = blockdev_get_device_size(partition_fd, &current_size);
if (r < 0)
return r;
if (size == UINT64_MAX && offset == UINT64_MAX)
return 0;

View File

@@ -22,12 +22,14 @@ struct LoopDevice {
sd_device *dev;
char *backing_file;
bool relinquished;
bool created; /* If we created the device */
dev_t backing_devno; /* The backing file's dev_t */
ino_t backing_inode; /* The backing file's ino_t */
uint64_t diskseq; /* Block device sequence number, monothonically incremented by the kernel on create/attach, or 0 if we don't know */
uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */
usec_t timestamp_not_before; /* CLOCK_MONOTONIC timestamp taken immediately before attaching the loopback device, or USEC_INFINITY if we don't know */
uint32_t sector_size;
uint64_t device_size;
};
/* Returns true if LoopDevice object is not actually a loopback device but some other block device we just wrap */