btrfs-progs icon indicating copy to clipboard operation
btrfs-progs copied to clipboard

btrfs device ready incorrectly reports sprout device isn't ready, boot failure

Open cmurf opened this issue 4 years ago • 2 comments

kernel 5.11.12 btrfs-progs 5.11.1

A seed and sprout are created on /dev/vda3 and /dev/vda4 respectively as follows:

# btrfs fi show
,,,
Label: 'rescue'  uuid: 97bd44f5-c586-47cf-b760-c00f42676b23
	Total devices 1 FS bytes used 2.32GiB
	devid    1 size 3.27GiB used 2.67GiB path /dev/vda3

Label: 'sprout'  uuid: 1b300322-5b9e-4a0d-936c-227ffe9b635d
	Total devices 2 FS bytes used 2.32GiB
	devid    1 size 3.27GiB used 2.66GiB path /dev/vda3
	devid    2 size 28.13GiB used 1.28GiB path /dev/vda4

Both mount and function as expected, except when the sprout is used as a root file system, i.e. root=UUID=1b300322-5b9e-4a0d-936c-227ffe9b635d there is an indefinite hang.

Turns out, it's not ready for some reason.

# btrfs device ready /dev/vda3
# echo $?
0
# btrfs device ready /dev/vda4
# echo $?
1

The consequence of this is /usr/lib/udev/rules.d/64-btrfs.rules polls 'btrfs device ready' to know when to mount and proceed with boot. Since it's not ready, udevadm info shows:

E: ID_BTRFS_READY=0 E: SYSTEMD_READY=0

And therefore mount is never attempt, with systemd/udev waiting indefinitely.

cmurf avatar Apr 25 '21 06:04 cmurf

By reading seed device code, I'd say that it's hard to let btrfs device ready to detect the status of sprout device. Without a previous mount(reading dev item in chunk tree), btrfs has no information about its seed device. Because fsids in seed device and sprout device differ. Even the seed device was detected and BTRFS_IOC_DEVICES_READY is calling, btrfs can't recognize its seed device then it thinks the sprout is not ready (total_devices(2) != num_device(1)).

Damenly avatar Apr 25 '21 12:04 Damenly

I've spent some time on and off looking into this and generally agree with Damenly. As-is the connection from the sprout device back to the existence of the seed device is really lacking, due to the fsid change, and only gets properly populated after reading the dev items in the chunk tree.

I thought about it a bit more and thought of a possible hack using the sys_array that is on each device's superblock: In a sprout device, the sys array does not contain the seed device, but in a legitimate multi-device system, it ought to. I tried to implement this hack and got hung up bootstrapping the sys array from the ready ioctl, so I honestly don't think this is a good approach, as it got ugly fast, unless we think we want read the sys array in a much more standalone way than how it's done in open_ctree.

Another option I considered, but which is less "free" is to simply include the fsid of the seed (or uuids of all seed devices) in the sprout's sb as a new field. That seems like the better, less hacky way to fix this.

boryas avatar Jun 25 '21 21:06 boryas