From: Daan De Meyer Date: Wed, 27 Jul 2022 21:11:37 +0000 (+0200) Subject: blockdev-util: Introduce fd_get_whole_disk() X-Git-Tag: v252-rc1~521^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=26aa4800f8dd863f5ae9dbda8ae37c5ea57ce65b;p=thirdparty%2Fsystemd.git blockdev-util: Introduce fd_get_whole_disk() Extracted from find_devno() in udevadm-lock.c. --- diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index c3b90bb2273..de72f843826 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -377,3 +377,51 @@ int path_is_encrypted(const char *path) { return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */); } + +int fd_get_whole_disk(int fd, bool backing, dev_t *ret) { + dev_t devt; + struct stat st; + int r; + + assert(ret); + + if (fstat(fd, &st) < 0) + return -errno; + + if (S_ISBLK(st.st_mode)) + devt = st.st_rdev; + else if (!backing) + return -ENOTBLK; + else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) + return -ENOTBLK; + else if (major(st.st_dev) != 0) + devt = st.st_dev; + else { + _cleanup_close_ int regfd = -1; + + /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special + * handing, to get the backing device node. */ + + regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (regfd < 0) + return regfd; + + r = btrfs_get_block_device_fd(regfd, &devt); + if (r == -ENOTTY) + return -ENOTBLK; + if (r < 0) + return r; + } + + return block_get_whole_disk(devt, ret); +} + +int path_get_whole_disk(const char *path, bool backing, dev_t *ret) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_CLOEXEC|O_PATH); + if (fd < 0) + return -errno; + + return fd_get_whole_disk(fd, backing, ret); +} diff --git a/src/shared/blockdev-util.h b/src/shared/blockdev-util.h index 05501f26570..e30692b509a 100644 --- a/src/shared/blockdev-util.h +++ b/src/shared/blockdev-util.h @@ -27,3 +27,6 @@ int blockdev_partscan_enabled(int fd); int fd_is_encrypted(int fd); int path_is_encrypted(const char *path); + +int fd_get_whole_disk(int fd, bool backing, dev_t *ret); +int path_get_whole_disk(const char *path, bool backing, dev_t *ret); diff --git a/src/udev/udevadm-lock.c b/src/udev/udevadm-lock.c index 60d6507aaf2..a1e04f65166 100644 --- a/src/udev/udevadm-lock.c +++ b/src/udev/udevadm-lock.c @@ -144,9 +144,7 @@ static int find_devno( const char *device, bool backing) { - _cleanup_close_ int fd = -1; - dev_t devt, whole_devt; - struct stat st; + dev_t devt; int r; assert(devnos); @@ -154,51 +152,19 @@ static int find_devno( assert(*devnos || *n_devnos == 0); assert(device); - fd = open(device, O_CLOEXEC|O_PATH); - if (fd < 0) - return log_error_errno(errno, "Failed to open '%s': %m", device); - - if (fstat(fd, &st) < 0) - return log_error_errno(errno, "Failed to stat '%s': %m", device); - - if (S_ISBLK(st.st_mode)) - devt = st.st_rdev; - else if (!backing) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device: %s", device); - else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device, regular file or directory: %s", device); - else if (major(st.st_dev) != 0) - devt = st.st_dev; - else { - _cleanup_close_ int regfd = -1; - - /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special - * handing, to get the backing device node. */ - - regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (regfd < 0) - return log_error_errno(regfd, "Failed to open '%s': %m", device); - - r = btrfs_get_block_device_fd(regfd, &devt); - if (r == -ENOTTY) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Path '%s' not backed by block device.", device); - if (r < 0) - return log_error_errno(r, "Failed to acquire btrfs backing device of '%s': %m", device); - } - - r = block_get_whole_disk(devt, &whole_devt); + r = path_get_whole_disk(device, backing, &devt); if (r < 0) return log_error_errno(r, "Failed to find whole block device for '%s': %m", device); - if (typesafe_bsearch(&whole_devt, *devnos, *n_devnos, devt_compare_func)) { - log_debug("Device %u:%u already listed for locking, ignoring.", major(whole_devt), minor(whole_devt)); + if (typesafe_bsearch(&devt, *devnos, *n_devnos, devt_compare_func)) { + log_debug("Device %u:%u already listed for locking, ignoring.", major(devt), minor(devt)); return 0; } if (!GREEDY_REALLOC(*devnos, *n_devnos + 1)) return log_oom(); - (*devnos)[(*n_devnos)++] = whole_devt; + (*devnos)[(*n_devnos)++] = devt; /* Immediately sort again, to ensure the binary search above will work for the next device we add */ typesafe_qsort(*devnos, *n_devnos, devt_compare_func);