Skip to content

Commit 5f1bc5f

Browse files
committed
Merge branch 'github-pull-54'
The btrfs feature currently lacks support for booting from RAID configurations (RAID1, RAID10, etc.), making it impossible to handle systems with redundant boot storage. Additionally, when member devices are missing due to hardware failure, the boot process panics instead of gracefully degrading. By Sergey Konev * github-pull-54: feature/btrfs: Add multi-device (RAID) boot support Link: #54 Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
2 parents b2f8221 + 6067047 commit 5f1bc5f

10 files changed

Lines changed: 197 additions & 0 deletions

File tree

.github/workflows/testcases.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ jobs:
2020
strategy:
2121
matrix:
2222
testcase:
23+
- btrfs-raid1
24+
- btrfs-raid1-degraded
2325
- btrfs-subvol
2426
- efi-partition
2527
- efi-reqpartition

features/btrfs/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
11
# Feature: btrfs
22

33
Feature adds btrfs to initramfs.
4+
5+
## Multi-device support
6+
7+
For multi-device btrfs filesystems (RAID), the feature waits for all component
8+
devices to appear before allowing mount. If some devices are missing after the
9+
timeout, the `degraded` mount option is added automatically so the filesystem
10+
can be mounted with available devices.
11+
12+
## Boot parameters
13+
14+
- `btrfs-member-delay=<SECS>` - determines the number of seconds to wait after
15+
the last btrfs member device appears before mounting in degraded mode
16+
(default: 10 seconds). If this value is zero, it means disabling the degraded
17+
mount support.

features/btrfs/config.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ BTRFS_UDEV_RULES := $(wildcard $(FEATURESDIR)/btrfs/rules.d/*.rules)
55
BTRFS_PROGS = btrfs
66
BTRFS_PRELOAD = btrfs
77
BTRFS_MODULES = crc32c
8+
9+
BTRFS_DATADIR = \
10+
$(FEATURESDIR)/btrfs/data
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
register_parameter number BTRFS_MEMBER_DELAY 10
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash -efu
2+
3+
. /.initrd/initenv
4+
. uevent-sh-functions
5+
6+
mkdir -p "$filterdir/btrfs-member/.tmp"
7+
8+
event="$(make_event btrfs-member)"
9+
release_event btrfs-member "$event"
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/bin/bash -eu
2+
3+
. shell-error
4+
. initrd-sh-functions
5+
. uevent-sh-functions
6+
. /.initrd/initenv
7+
8+
PROG="${QUEUE:--}: session=${SESSION:-0}: $PROG"
9+
message_time=1
10+
11+
pidfile="/var/run/$PROG.pid"
12+
tsfile=/.initrd/btrfs-member-timeout
13+
delay="${BTRFS_MEMBER_DELAY-}"
14+
15+
for e in "$1"/btrfs-member.*; do
16+
done_event "$e" ||:
17+
done
18+
19+
[ -n "$delay" ] && [ "$delay" -gt 0 ] ||
20+
exit 0
21+
22+
now="$(timestamp boottime raw)"
23+
now="${now%.*}"
24+
echo "$(($now + $delay))" > "$tsfile"
25+
26+
[ ! -e "$pidfile" ] ||
27+
exit 0
28+
29+
btrfs_fstab_entries()
30+
{
31+
local fsdev fsdir fstype fsopts freq passno uuid
32+
33+
while read -r fsdev fsdir fstype fsopts freq passno; do
34+
[ -n "$fsdev" ] || continue
35+
case "$fstype" in
36+
btrfs|auto) ;;
37+
*) continue ;;
38+
esac
39+
40+
case "$fsdev" in
41+
UUID=*)
42+
uuid="${fsdev#UUID=}"
43+
printf '%s %s\n' "$fsdev" "$uuid"
44+
;;
45+
LABEL=*)
46+
uuid="$(blkid -l -o value -s UUID -t "$fsdev" 2>/dev/null)" ||:
47+
[ -z "$uuid" ] || printf '%s %s\n' "$fsdev" "$uuid"
48+
;;
49+
esac
50+
done < /etc/fstab
51+
}
52+
53+
check_btrfs_arrays()
54+
{
55+
local fsdev uuid show total missing need_wait=
56+
57+
while read -r fsdev uuid; do
58+
show="$(btrfs filesystem show "$uuid" 2>/dev/null)" ||
59+
continue
60+
61+
total="$(printf '%s\n' "$show" |
62+
sed -n 's/.*Total devices \([0-9]\+\).*/\1/p')"
63+
64+
[ -n "$total" ] && [ "$total" -gt 1 ] ||
65+
continue
66+
67+
missing="$(printf '%s\n' "$show" | grep -c 'missing' ||:)"
68+
69+
if [ "${missing:-0}" -gt 0 ]; then
70+
need_wait=1
71+
fi
72+
done < <(btrfs_fstab_entries | sort -u -k2,2)
73+
74+
[ -n "$need_wait" ]
75+
}
76+
77+
# No multi-device btrfs in fstab, or all devices already present.
78+
check_btrfs_arrays ||
79+
exit 0
80+
81+
(
82+
while :; do
83+
now="$(timestamp boottime raw)"
84+
now="${now%.*}"
85+
86+
ts=
87+
readline ts "$tsfile"
88+
89+
[ "$ts" -ge "$now" ] ||
90+
break
91+
sleep 1
92+
done
93+
94+
# Run a full device scan to resolve any per-device scan race conditions.
95+
btrfs device scan ||:
96+
97+
changed=
98+
while read -r fsdev uuid; do
99+
show="$(btrfs filesystem show "$uuid" 2>/dev/null)" ||
100+
continue
101+
102+
total="$(printf '%s\n' "$show" |
103+
sed -n 's/.*Total devices \([0-9]\+\).*/\1/p')"
104+
105+
[ -n "$total" ] && [ "$total" -gt 1 ] ||
106+
continue
107+
108+
missing="$(printf '%s\n' "$show" | grep -c 'missing' ||:)"
109+
110+
if [ "${missing:-0}" -gt 0 ]; then
111+
message "btrfs $uuid: $missing of $total device(s) missing, adding degraded mount option"
112+
113+
# shellcheck disable=SC2016
114+
fsdev_escaped="$(printf '%s\n' "$fsdev" | sed 's/[[\.*^$()+?{|]/\\&/g')"
115+
if ! grep -qE "^${fsdev_escaped}[[:space:]].*degraded" /etc/fstab; then
116+
sed -i "/^${fsdev_escaped}[[:space:]]/s/\(auto\|btrfs\)\([[:space:]]\+\)/btrfs\2degraded,/" /etc/fstab
117+
changed=1
118+
fi
119+
else
120+
message "btrfs $uuid: all $total devices present"
121+
fi
122+
done < <(btrfs_fstab_entries | sort -u -k2,2)
123+
124+
[ -z "$changed" ] ||
125+
rootdelay_reset_timer
126+
) &
127+
128+
echo "$!" > "$pidfile"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
SUBSYSTEM=="block", ACTION!="remove", ENV{ID_FS_TYPE}=="btrfs", RUN+="/bin/udev-run btrfs device scan $env{DEVNAME}"
2+
SUBSYSTEM=="block", ACTION!="remove", ENV{ID_FS_TYPE}=="btrfs", RUN+="/lib/uevent/filters/btrfs-member"

features/btrfs/rules.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ MODULES_ADD += $(BTRFS_MODULES)
44

55
PUT_UDEV_RULES += $(BTRFS_UDEV_RULES)
66
PUT_FEATURE_PROGS += $(BTRFS_PROGS)
7+
PUT_FEATURE_DIRS += $(BTRFS_DATADIR)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# param KICKSTART_DISKS=3
2+
# param BOOT_DISKS=2
3+
# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=fs rootflags=subvol=root"
4+
5+
ignoredisk --drives=LABEL=SYSIMAGE
6+
clearpart --all --initlabel --disklabel=mbr
7+
8+
part /boot --size=100% --fstype=ext4 --label=BOOT
9+
10+
part btrfs.01 --size=100%
11+
part btrfs.02 --size=100%
12+
13+
btrfs none --data=1 --metadata=1 --label=fs btrfs.0*
14+
15+
btrfs / --subvol --name=root LABEL=fs
16+
17+
liveimg --url=dir:///sysimage/
18+
19+
shutdown

testing/test-root-btrfs-raid1.cfg

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# param KICKSTART_DISKS=3
2+
# param BOOT_DISKS=3
3+
# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=fs rootflags=subvol=root"
4+
5+
ignoredisk --drives=LABEL=SYSIMAGE
6+
clearpart --all --initlabel --disklabel=mbr
7+
8+
part /boot --size=100% --fstype=ext4 --label=BOOT
9+
10+
part btrfs.01 --size=100%
11+
part btrfs.02 --size=100%
12+
13+
btrfs none --data=1 --metadata=1 --label=fs btrfs.0*
14+
15+
btrfs / --subvol --name=root LABEL=fs
16+
17+
liveimg --url=dir:///sysimage/
18+
19+
shutdown

0 commit comments

Comments
 (0)