New issue
Advanced search Search tips

Issue 702400 link

Starred by 0 users

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Chrome
Pri: 3
Type: Bug



Sign in to add a comment

rootdev: stat checks don't work on btrfs

Project Member Reported by xiaochu@chromium.org, Mar 16 2017

Issue description

OS: 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.

 
Cc: vapier@chromium.org
Components: 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.

Comment 2 by vapier@chromium.org, Mar 17 2017

Labels: OS-Chrome
Summary: rootdev: stat checks don't work on btrfs (was: unexpected linux stat behavior in rootdev)
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?
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

Comment 5 by vapier@chromium.org, 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.
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.
Labels: Restrict-View-Google
Labels: -Restrict-View-Google
Project Member

Comment 9 by bugdroid1@chromium.org, 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

Owner: xiaochu@chromium.org
Status: Fixed (was: Untriaged)
instead of relying on stat, we decide to use ioctl to read the dev path directly.
Status: Started (was: Fixed)
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...
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.
Unfortunately, lsblk does not print mountpoint '/' at init stage either...
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.
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