]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
blockdev-util: Introduce fd_get_whole_disk()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 27 Jul 2022 21:11:37 +0000 (23:11 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 3 Aug 2022 18:55:00 +0000 (20:55 +0200)
Extracted from find_devno() in udevadm-lock.c.

src/shared/blockdev-util.c
src/shared/blockdev-util.h
src/udev/udevadm-lock.c

index c3b90bb22734a664526f38a58ac6ef723a1336f9..de72f8438265e426bcdb1f40ef8d7cdfb676fa82 100644 (file)
@@ -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);
+}
index 05501f26570af901d98e3442167977b766a29d29..e30692b509ad6ad71020ab5a549cb5951f0c6230 100644 (file)
@@ -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);
index 60d6507aaf27800ea85b448b08a7925f36601f8d..a1e04f651663a8327ab6e9ccd088a12db6d311d6 100644 (file)
@@ -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);