rootdev: stat checks don't work on btrfs |
||||||
Issue descriptionOS: chrome OS What steps will reproduce the problem? (1) enable btrfs on rootfs (use this patch: https://chromium-review.googlesource.com/#/c/456582/, then change fs_format to be 'btrfs' in build_library/legacy_disk_layout.json ) (2) usb boot fails and replace 'ROOT_DEV=${rootdev -s}' with 'ROOT_DEV=/dev/sdb3' in chromeos_start, you are able to start (3) after login, 'rootdev -s' fails. What is the expected result? rootdev should print rootfs device. system should boot without hacking. What happens instead? rootdev returns nothing system crashes at startup Please use labels and text to provide additional information. gwendal@ identifies the problem is in stat system call. For graphics-related bugs, please copy/paste the contents of the about:gpu page at the end of this report.
,
Mar 17 2017
,
Mar 17 2017
I am trying btrfs command: https://github.com/kdave/btrfs-progs/blob/devel/Documentation/btrfs.asciidoc localhost ~ # btrfs filesystem show / Label: 'ROOT-A' uuid: 1bd07af3-c020-4759-8cfe-106afc662d16 Total devices 1 FS bytes used 1.19GiB devid 1 size 1.95GiB used 1.94GiB path /dev/sdb3 Is the main point of rootdev is to return the rootfs device? Can we use btrfs command to return us the correct device?
,
Mar 17 2017
Based on btrfs-progs, maybe we have two options?: 1) install btrfs-progs and call 'btrfs filesystem show /' to get the path; 2) implement this in rootdev in reference for:https://github.com/kdave/btrfs-progs/blob/devel/cmds-filesystem.c#L776
,
Mar 17 2017
yes, the rootdev project is about finding the device that backs the root mount. a seemingly simple question. `rootdev` is merely a frontend to librootdev. the program is used in scripts while the library is used in other system programs. i'm not sure forking+execing btrfs from a library is a good approach, plus we'd need to parse its output to actually pull out the "/dev/sda3" from your output.
,
Mar 17 2017
Thanks, vapier! I made a temporary patch (do not merge): https://chromium-review.googlesource.com/#/c/457138/ to hack around btrfs. Now I'm able to install a system with btrfs rootfilesystem to measure performance.
,
Mar 22 2017
,
Mar 22 2017
,
Apr 26 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromiumos/third_party/rootdev/+/b9b8f1de0ab9d4b0e1739d7c0dc4ec232b85a5c3 commit b9b8f1de0ab9d4b0e1739d7c0dc4ec232b85a5c3 Author: Xiaochu Liu <xiaochu@chromium.org> Date: Wed Apr 26 01:40:04 2017 third_party/rootdev: support btrfs using ioctl rootdev assumes only one device exist for an FS (which is true for ext2/squashfs). FS like btrfs supports multiple devices and uses an anonymous namespace for each device number. Thus sys call 'stat' no longer works for btrfs. This change adds a function rootdev_wrapper_btrfs in which we use ioctl to read the ioctl dev info from device directly. Then in main.c and rootdev library call, we predicate on FS type to decide whether call rootdev_wrapper or rootdev_wrapper_btrfs. BUG=chromium:702400, chromium:698296 TEST=manual Change-Id: I4a388192026ec36dd02c810cf5f31d02f5a87988 Reviewed-on: https://chromium-review.googlesource.com/486263 Commit-Ready: Xiaochu Liu <xiaochu@chromium.org> Tested-by: Xiaochu Liu <xiaochu@chromium.org> Reviewed-by: Mike Frysinger <vapier@chromium.org> [modify] https://crrev.com/b9b8f1de0ab9d4b0e1739d7c0dc4ec232b85a5c3/rootdev.c [modify] https://crrev.com/b9b8f1de0ab9d4b0e1739d7c0dc4ec232b85a5c3/rootdev.h [modify] https://crrev.com/b9b8f1de0ab9d4b0e1739d7c0dc4ec232b85a5c3/main.c
,
Apr 26 2017
instead of relying on stat, we decide to use ioctl to read the dev path directly.
,
Apr 27 2017
I found out the reason why our system depends on rootdev to search for the path at boot time: Since in mountinfo '/dev/root' is always listed as the root device which does not exist at all in Chrome OS. rootdev has to search for actual device by matching device major/minor number. However, it's no longer worker any more for btrfs since stat returns virtual device number which is not actual device number. Last change uses syscall ioctl to report root device path which works fine once system is booted up. But at boot (init) stage, ioctl reports '/dev/root' again which is wrong. I was confused... Actual device should have been mounted to '/' otherwise for ext2 rootdev (stat) won't report correct device ID... If we really need to do a search and device ID isn't easily accessible, how about PARTUUID? For example, 'cat /prof/cmdline' shows me 'root=PARTUUID=xxx/PARTNROFF=1' and we can search to find real device /dev/yyy2 for this PARTUUID which is the kernel partition. Then the question is whether root device is /dev/yyy3 or /dev/yyy5...
,
Apr 27 2017
I found another potential - lsblk utility lists all block devices and its mount point: localhost ~ # lsblk lsblk: dm-0: failed to get device path NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT .(ignore).. |-sdb2 8:18 1 16M 0 part |-sdb3 8:19 1 2G 0 part / |-sdb4 8:20 1 16M 0 part .(ignore).. Notice that lsblk is not working properly with dm mount.
,
Apr 27 2017
Unfortunately, lsblk does not print mountpoint '/' at init stage either...
,
Apr 27 2017
as you can see in chromeos_startup, we utilize rootdev not just to operate on the rootdev, but as a way of finding the disk that holds all the partitions. that way we can get from /dev/sda3 (ROOT-A) to /dev/sda1 (stateful) and such. with btrfs, i'm not seeing how we can't do the same thing. we don't care about the btrfs notion of dev paths ... we want to know /dev/sda3 regardless of the fs format.
,
Apr 27 2017
When rootfs is in btrfs, rootdev still works properly with any other partitions since they are in ext. The specific case we are handling here is find rootdev on btrfs mounted at '/' at boot time. Tricky thing is 'stat' or 'mount' does not report any info about dev path and dev id reported is meaningless (a number that changes even for different files on same device). So our old approach to search device path based on dev id fails. My last fix depends on ioctl which works after boot process is done but reports '/dev/root' as rootfs path which is a place holder (does not exist in Chrome OS) set by linux kernel. A solution I'm working on extracts partuuid from kernel command line and then find the device (partition) with this partuuid+1. |
||||||
►
Sign in to add a comment |
||||||
Comment 1 by gwendal@chromium.org
, Mar 16 2017Components: OS>Installer
rootdev is doing "stat('/', &path_stat)" and expects path_stat.st_dev to contains the physical device (major,minor) [when we are not using dm]. But that does not work on btrfs: btrfs includes a virtualization layer and export anonymous device to VFS: see https://www.spinics.net/lists/linux-btrfs/msg59039.html for more details.