summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/blockdev-util.c199
-rw-r--r--src/basic/blockdev-util.h38
-rw-r--r--src/basic/btrfs-util.c1
-rw-r--r--src/basic/device-nodes.h5
-rw-r--r--src/basic/meson.build6
-rw-r--r--src/basic/util.c168
-rw-r--r--src/basic/util.h5
-rw-r--r--src/core/cgroup.c3
-rw-r--r--src/core/umount.c3
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c1
-rw-r--r--src/partition/growfs.c1
-rw-r--r--src/shared/dissect-image.c1
12 files changed, 249 insertions, 182 deletions
diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c
new file mode 100644
index 0000000000..3a8f8d1c27
--- /dev/null
+++ b/src/basic/blockdev-util.c
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+#include "alloc-util.h"
+#include "blockdev-util.h"
+#include "btrfs-util.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "missing.h"
+#include "stat-util.h"
+
+int block_get_whole_disk(dev_t d, dev_t *ret) {
+ char p[SYS_BLOCK_PATH_MAX("/partition")];
+ _cleanup_free_ char *s = NULL;
+ unsigned n, m;
+ int r;
+
+ assert(ret);
+
+ /* If it has a queue this is good enough for us */
+ xsprintf_sys_block_path(p, "/queue", d);
+ if (access(p, F_OK) >= 0) {
+ *ret = d;
+ return 0;
+ }
+
+ /* If it is a partition find the originating device */
+ xsprintf_sys_block_path(p, "/partition", d);
+ if (access(p, F_OK) < 0)
+ return -ENOENT;
+
+ /* Get parent dev_t */
+ xsprintf_sys_block_path(p, "/../dev", d);
+ r = read_one_line_file(p, &s);
+ if (r < 0)
+ return r;
+
+ r = sscanf(s, "%u:%u", &m, &n);
+ if (r != 2)
+ return -EINVAL;
+
+ /* Only return this if it is really good enough for us. */
+ xsprintf_sys_block_path(p, "/queue", makedev(m, n));
+ if (access(p, F_OK) < 0)
+ return -ENOENT;
+
+ *ret = makedev(m, n);
+ return 0;
+}
+
+int get_block_device(const char *path, dev_t *dev) {
+ struct stat st;
+ struct statfs sfs;
+
+ assert(path);
+ assert(dev);
+
+ /* Get's the block device directly backing a file system. If
+ * the block device is encrypted, returns the device mapper
+ * block device. */
+
+ if (lstat(path, &st))
+ return -errno;
+
+ if (major(st.st_dev) != 0) {
+ *dev = st.st_dev;
+ return 1;
+ }
+
+ if (statfs(path, &sfs) < 0)
+ return -errno;
+
+ if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
+ return btrfs_get_block_device(path, dev);
+
+ return 0;
+}
+
+int get_block_device_harder(const char *path, dev_t *dev) {
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_free_ char *t = NULL;
+ char p[SYS_BLOCK_PATH_MAX("/slaves")];
+ struct dirent *de, *found = NULL;
+ const char *q;
+ unsigned maj, min;
+ dev_t dt;
+ int r;
+
+ assert(path);
+ assert(dev);
+
+ /* Gets the backing block device for a file system, and
+ * handles LUKS encrypted file systems, looking for its
+ * immediate parent, if there is one. */
+
+ r = get_block_device(path, &dt);
+ if (r <= 0)
+ return r;
+
+ xsprintf_sys_block_path(p, "/slaves", dt);
+ d = opendir(p);
+ if (!d) {
+ if (errno == ENOENT)
+ goto fallback;
+
+ return -errno;
+ }
+
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
+
+ if (dot_or_dot_dot(de->d_name))
+ continue;
+
+ if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+ continue;
+
+ if (found) {
+ _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
+
+ /* We found a device backed by multiple other devices. We don't really support automatic
+ * discovery on such setups, with the exception of dm-verity partitions. In this case there are
+ * two backing devices: the data partition and the hash partition. We are fine with such
+ * setups, however, only if both partitions are on the same physical device. Hence, let's
+ * verify this. */
+
+ u = strjoin(p, "/", de->d_name, "/../dev");
+ if (!u)
+ return -ENOMEM;
+
+ v = strjoin(p, "/", found->d_name, "/../dev");
+ if (!v)
+ return -ENOMEM;
+
+ r = read_one_line_file(u, &a);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read %s: %m", u);
+ goto fallback;
+ }
+
+ r = read_one_line_file(v, &b);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read %s: %m", v);
+ goto fallback;
+ }
+
+ /* Check if the parent device is the same. If not, then the two backing devices are on
+ * different physical devices, and we don't support that. */
+ if (!streq(a, b))
+ goto fallback;
+ }
+
+ found = de;
+ }
+
+ if (!found)
+ goto fallback;
+
+ q = strjoina(p, "/", found->d_name, "/dev");
+
+ r = read_one_line_file(q, &t);
+ if (r == -ENOENT)
+ goto fallback;
+ if (r < 0)
+ return r;
+
+ if (sscanf(t, "%u:%u", &maj, &min) != 2)
+ return -EINVAL;
+
+ if (maj == 0)
+ goto fallback;
+
+ *dev = makedev(maj, min);
+ return 1;
+
+fallback:
+ *dev = dt;
+ return 1;
+}
diff --git a/src/basic/blockdev-util.h b/src/basic/blockdev-util.h
new file mode 100644
index 0000000000..642b7ce522
--- /dev/null
+++ b/src/basic/blockdev-util.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/types.h>
+
+#include "macro.h"
+#include "stdio-util.h"
+#include "string-util.h"
+
+#define SYS_BLOCK_PATH_MAX(suffix) \
+ (STRLEN("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix))
+#define xsprintf_sys_block_path(buf, suffix, devno) \
+ xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
+
+int block_get_whole_disk(dev_t d, dev_t *ret);
+
+int get_block_device(const char *path, dev_t *dev);
+
+int get_block_device_harder(const char *path, dev_t *dev);
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index f8d743b407..19d385ab7c 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -38,6 +38,7 @@
#endif
#include "alloc-util.h"
+#include "blockdev-util.h"
#include "btrfs-ctree.h"
#include "btrfs-util.h"
#include "chattr-util.h"
diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h
index 7dd8a772a5..49f4ccc729 100644
--- a/src/basic/device-nodes.h
+++ b/src/basic/device-nodes.h
@@ -29,11 +29,6 @@
int encode_devnode_name(const char *str, char *str_enc, size_t len);
int whitelisted_char_for_devnode(char c, const char *additional);
-#define SYS_BLOCK_PATH_MAX(suffix) \
- (STRLEN("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix))
-#define xsprintf_sys_block_path(buf, suffix, devno) \
- xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix))
-
#define DEV_NUM_PATH_MAX \
(STRLEN("/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t))
#define xsprintf_dev_num_path(buf, type, devno) \
diff --git a/src/basic/meson.build b/src/basic/meson.build
index f751ee3215..31a00cee5e 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -35,6 +35,8 @@ basic_sources_plain = files('''
bitmap.c
bitmap.h
blkid-util.h
+ blockdev-util.c
+ blockdev-util.h
bpf-program.c
bpf-program.h
btrfs-ctree.h
@@ -203,10 +205,10 @@ basic_sources_plain = files('''
time-util.h
umask-util.h
unaligned.h
- unit-name.c
- unit-name.h
unit-def.c
unit-def.h
+ unit-name.c
+ unit-name.h
user-util.c
user-util.h
utf8.c
diff --git a/src/basic/util.c b/src/basic/util.c
index 53bfb9e0da..5dd3c3014f 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -118,45 +118,6 @@ int socket_from_display(const char *display, char **path) {
return 0;
}
-int block_get_whole_disk(dev_t d, dev_t *ret) {
- char p[SYS_BLOCK_PATH_MAX("/partition")];
- _cleanup_free_ char *s = NULL;
- int r;
- unsigned n, m;
-
- assert(ret);
-
- /* If it has a queue this is good enough for us */
- xsprintf_sys_block_path(p, "/queue", d);
- if (access(p, F_OK) >= 0) {
- *ret = d;
- return 0;
- }
-
- /* If it is a partition find the originating device */
- xsprintf_sys_block_path(p, "/partition", d);
- if (access(p, F_OK) < 0)
- return -ENOENT;
-
- /* Get parent dev_t */
- xsprintf_sys_block_path(p, "/../dev", d);
- r = read_one_line_file(p, &s);
- if (r < 0)
- return r;
-
- r = sscanf(s, "%u:%u", &m, &n);
- if (r != 2)
- return -EINVAL;
-
- /* Only return this if it is really good enough for us. */
- xsprintf_sys_block_path(p, "/queue", makedev(m, n));
- if (access(p, F_OK) < 0)
- return -ENOENT;
-
- *ret = makedev(m, n);
- return 0;
-}
-
bool kexec_loaded(void) {
_cleanup_free_ char *s = NULL;
@@ -592,132 +553,3 @@ int version(void) {
SYSTEMD_FEATURES);
return 0;
}
-
-int get_block_device(const char *path, dev_t *dev) {
- struct stat st;
- struct statfs sfs;
-
- assert(path);
- assert(dev);
-
- /* Get's the block device directly backing a file system. If
- * the block device is encrypted, returns the device mapper
- * block device. */
-
- if (lstat(path, &st))
- return -errno;
-
- if (major(st.st_dev) != 0) {
- *dev = st.st_dev;
- return 1;
- }
-
- if (statfs(path, &sfs) < 0)
- return -errno;
-
- if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
- return btrfs_get_block_device(path, dev);
-
- return 0;
-}
-
-int get_block_device_harder(const char *path, dev_t *dev) {
- _cleanup_closedir_ DIR *d = NULL;
- _cleanup_free_ char *t = NULL;
- char p[SYS_BLOCK_PATH_MAX("/slaves")];
- struct dirent *de, *found = NULL;
- const char *q;
- unsigned maj, min;
- dev_t dt;
- int r;
-
- assert(path);
- assert(dev);
-
- /* Gets the backing block device for a file system, and
- * handles LUKS encrypted file systems, looking for its
- * immediate parent, if there is one. */
-
- r = get_block_device(path, &dt);
- if (r <= 0)
- return r;
-
- xsprintf_sys_block_path(p, "/slaves", dt);
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT)
- goto fallback;
-
- return -errno;
- }
-
- FOREACH_DIRENT_ALL(de, d, return -errno) {
-
- if (dot_or_dot_dot(de->d_name))
- continue;
-
- if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
- continue;
-
- if (found) {
- _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
-
- /* We found a device backed by multiple other devices. We don't really support automatic
- * discovery on such setups, with the exception of dm-verity partitions. In this case there are
- * two backing devices: the data partition and the hash partition. We are fine with such
- * setups, however, only if both partitions are on the same physical device. Hence, let's
- * verify this. */
-
- u = strjoin(p, "/", de->d_name, "/../dev");
- if (!u)
- return -ENOMEM;
-
- v = strjoin(p, "/", found->d_name, "/../dev");
- if (!v)
- return -ENOMEM;
-
- r = read_one_line_file(u, &a);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", u);
- goto fallback;
- }
-
- r = read_one_line_file(v, &b);
- if (r < 0) {
- log_debug_errno(r, "Failed to read %s: %m", v);
- goto fallback;
- }
-
- /* Check if the parent device is the same. If not, then the two backing devices are on
- * different physical devices, and we don't support that. */
- if (!streq(a, b))
- goto fallback;
- }
-
- found = de;
- }
-
- if (!found)
- goto fallback;
-
- q = strjoina(p, "/", found->d_name, "/dev");
-
- r = read_one_line_file(q, &t);
- if (r == -ENOENT)
- goto fallback;
- if (r < 0)
- return r;
-
- if (sscanf(t, "%u:%u", &maj, &min) != 2)
- return -EINVAL;
-
- if (maj == 0)
- goto fallback;
-
- *dev = makedev(maj, min);
- return 1;
-
-fallback:
- *dev = dt;
- return 1;
-}
diff --git a/src/basic/util.h b/src/basic/util.h
index 62bf1a6961..8cd78171bc 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -71,8 +71,6 @@ bool plymouth_running(void);
bool display_is_local(const char *display) _pure_;
int socket_from_display(const char *display, char **path);
-int block_get_whole_disk(dev_t d, dev_t *ret);
-
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
@@ -191,6 +189,3 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
int update_reboot_parameter_and_warn(const char *param);
int version(void);
-
-int get_block_device(const char *path, dev_t *dev);
-int get_block_device_harder(const char *path, dev_t *dev);
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 78ef885b06..d08b4a0787 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -22,6 +22,7 @@
#include <fnmatch.h>
#include "alloc-util.h"
+#include "blockdev-util.h"
#include "bpf-firewall.h"
#include "cgroup-util.h"
#include "cgroup.h"
@@ -307,7 +308,7 @@ static int lookup_block_device(const char *p, dev_t *dev) {
/* If this is a partition, try to get the originating
* block device */
- block_get_whole_disk(*dev, dev);
+ (void) block_get_whole_disk(*dev, dev);
} else {
log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
return -ENODEV;
diff --git a/src/core/umount.c b/src/core/umount.c
index d8ccdfd6c2..b39181639a 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -28,6 +28,7 @@
#include "libudev.h"
#include "alloc-util.h"
+#include "blockdev-util.h"
#include "def.h"
#include "escape.h"
#include "fd-util.h"
@@ -35,12 +36,12 @@
#include "linux-3.13/dm-ioctl.h"
#include "list.h"
#include "mount-setup.h"
+#include "mount-util.h"
#include "path-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "umount.h"
-#include "mount-util.h"
#include "util.h"
#include "virt.h"
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 9e8b956d5c..85899ab301 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -28,6 +28,7 @@
#include "alloc-util.h"
#include "blkid-util.h"
+#include "blockdev-util.h"
#include "btrfs-util.h"
#include "dirent-util.h"
#include "dissect-image.h"
diff --git a/src/partition/growfs.c b/src/partition/growfs.c
index 901b33e39e..41b4e872be 100644
--- a/src/partition/growfs.c
+++ b/src/partition/growfs.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/vfs.h>
+#include "blockdev-util.h"
#include "crypt-util.h"
#include "device-nodes.h"
#include "dissect-image.h"
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index a11d4849bb..8fc9e97bbd 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -25,6 +25,7 @@
#include "architecture.h"
#include "ask-password-api.h"
#include "blkid-util.h"
+#include "blockdev-util.h"
#include "copy.h"
#include "crypt-util.h"
#include "def.h"