From: Lennart Poettering Date: Fri, 22 Dec 2017 14:22:59 +0000 (+0100) Subject: basic: split out blockdev-util.[ch] from util.h X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=a09384dde54cbb644b3c414ba8dec15112497cab;p=elogind.git basic: split out blockdev-util.[ch] from util.h With three functions it makes sense to split this out now. --- diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c new file mode 100644 index 000000000..b7b86ab2f --- /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 . +***/ + +//#include +//#include + +//#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/meson.build b/src/basic/meson.build index 5d9780e94..6b16b7967 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -36,6 +36,8 @@ # bitmap.c # bitmap.h # blkid-util.h +# blockdev-util.c +# blockdev-util.h # bpf-program.c # bpf-program.h # btrfs-ctree.h @@ -204,10 +206,10 @@ # 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 342c4bd09..19f189135 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -121,45 +121,6 @@ int socket_from_display(const char *display, char **path) { } #if 0 /// UNNEEDED by elogind -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; @@ -602,132 +563,4 @@ int version(void) { } #if 0 /// UNNEEDED by elogind -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; -} #endif // 0 diff --git a/src/basic/util.h b/src/basic/util.h index 30448a3b8..33c4854ee 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -74,9 +74,7 @@ bool display_is_local(const char *display) _pure_; int socket_from_display(const char *display, char **path); #if 0 /// UNNEEDED by elogind -int block_get_whole_disk(dev_t d, dev_t *ret); #endif // 0 - #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) @@ -205,6 +203,4 @@ int update_reboot_parameter_and_warn(const char *param); int version(void); #if 0 /// UNNEEDED by elogind -int get_block_device(const char *path, dev_t *dev); -int get_block_device_harder(const char *path, dev_t *dev); #endif // 0 diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 79f362fb6..161ea7dc8 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -22,6 +22,7 @@ #include #include "alloc-util.h" +//#include "blockdev-util.h" //#include "bpf-firewall.h" #include "cgroup-util.h" #include "cgroup.h" @@ -308,7 +309,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;