]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
btrfs: if BTRFS_IOC_DEV_INFO returns /dev/root generate a friendly error message
authorLennart Poettering <lennart@poettering.net>
Mon, 7 Sep 2020 16:50:41 +0000 (18:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 8 Sep 2020 16:10:26 +0000 (18:10 +0200)
On systems that boot without initrd on a btrfs root file systems the
BTRFS_IOC_DEV_INFO ioctl returns /dev/root as backing device. That
sucks, since that is not a real device visible to userspace.

Since this has been that way since forever, and it doesn't look like the
kernel will get fixed soon for this, let's at least generate a useful
error message in this case.

This is not a bug fix, just a tweak to make this more recognizable.

Once the kernel gets fixed to report the correct device nodes in this
case, in a way userspace can make sense of them things will magically
work for systemd, too.

(Note that this doesn't add a log message about this to really all cases
we call get_device() in, but just the main ones that are called in early
boot context, after all all there's no benefit in seeing this message
too many times.)

https://github.com/systemd/systemd/issues/16953
https://bugs.freedesktop.org/show_bug.cgi?id=84689
https://bugzilla.kernel.org/show_bug.cgi?id=89721

src/basic/btrfs-util.c
src/basic/btrfs-util.h
src/gpt-auto-generator/gpt-auto-generator.c
src/partition/growfs.c
src/partition/repart.c

index 71e1bc92eb7bfb4690e8f33f318e7cc1569a1d24..7de777073739c371ac6a20fa8703327c950e5e30 100644 (file)
@@ -315,6 +315,15 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
                         return -errno;
                 }
 
+                /* For the root fs — when no initrd is involved — btrfs returns /dev/root on any kernels from
+                 * the past few years. That sucks, as we have no API to determine the actual root then. let's
+                 * return an recognizable error for this case, so that the caller can maybe print a nice
+                 * message about this.
+                 *
+                 * https://bugzilla.kernel.org/show_bug.cgi?id=89721 */
+                if (path_equal((char*) di.path, "/dev/root"))
+                        return -EUCLEAN;
+
                 if (stat((char*) di.path, &st) < 0)
                         return -errno;
 
index c1bbb42ca1bdb98765d7321cb0bdac797d8ad76a..d9cb95af006740439302796fcd27701f8cd8d47b 100644 (file)
@@ -121,3 +121,9 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret);
 
 int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota);
 int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota);
+
+static inline int btrfs_log_dev_root(int level, int ret, const char *p) {
+        return log_full_errno(level, ret,
+                              "File system behind %s is reported by btrfs to be backed by pseudo-device /dev/root, which is not a valid userspace accessible device node. "
+                              "Cannot determine correct backing block device.", p);
+}
index 02d8837ca9b09b8119a5d2054a8881122257d8e0..d1c90266a8fe52fd5ed86dba2fd22c59161cb514 100644 (file)
@@ -729,10 +729,14 @@ static int add_mounts(void) {
         int r;
 
         r = get_block_device_harder("/", &devno);
+        if (r == -EUCLEAN)
+                return btrfs_log_dev_root(LOG_ERR, r, "root file system");
         if (r < 0)
                 return log_error_errno(r, "Failed to determine block device of root file system: %m");
         if (r == 0) {
                 r = get_block_device_harder("/usr", &devno);
+                if (r == -EUCLEAN)
+                        return btrfs_log_dev_root(LOG_ERR, r, "/usr");
                 if (r < 0)
                         return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
                 if (r == 0) {
index c097963e0cd741d56be0058fc62ecc9b980a09f6..8c1a84d981e12c9473f1e0fc59fa64bb9af91694 100644 (file)
@@ -11,6 +11,7 @@
 #include <sys/vfs.h>
 
 #include "blockdev-util.h"
+#include "btrfs-util.h"
 #include "cryptsetup-util.h"
 #include "device-nodes.h"
 #include "dissect-image.h"
@@ -212,6 +213,8 @@ static int run(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a mount point: %m", arg_target);
 
         r = get_block_device(arg_target, &devno);
+        if (r == -EUCLEAN)
+                return btrfs_log_dev_root(LOG_ERR, r, arg_target);
         if (r < 0)
                 return log_error_errno(r, "Failed to determine block device of \"%s\": %m", arg_target);
 
index bcbf2273e866013829fc3d3a0278da4f3b5399f6..f5015b73a13d5f87d1e75f9113f3b65da40cd1d0 100644 (file)
@@ -3369,6 +3369,8 @@ static int context_open_copy_block_paths(Context *context) {
                                 /* Special support for btrfs */
 
                                 r = btrfs_get_block_device_fd(source_fd, &devt);
+                                if (r == -EUCLEAN)
+                                        return btrfs_log_dev_root(LOG_ERR, r, p->copy_blocks_path);
                                 if (r < 0)
                                         return log_error_errno(r, "Unable to determine backing block device of '%s': %m", p->copy_blocks_path);
 
@@ -3833,6 +3835,8 @@ static int find_root(char **ret, int *ret_fd) {
                 }
 
                 r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd);
+                if (r == -EUCLEAN)
+                        return btrfs_log_dev_root(LOG_ERR, r, arg_node);
                 if (r < 0)
                         return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node);
 
@@ -3860,6 +3864,8 @@ static int find_root(char **ret, int *ret_fd) {
 
                 r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd);
                 if (r < 0) {
+                        if (r == -EUCLEAN)
+                                return btrfs_log_dev_root(LOG_ERR, r, p);
                         if (r != -ENODEV)
                                 return log_error_errno(r, "Failed to determine backing device of %s: %m", p);
                 } else