Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 817905 | Differences between
and this patch

Collapse All | Expand All

(-)file_not_specified_in_diff (-20 / +318 lines)
Line  Link Here
0
-- a/common.sh
0
++ b/common.sh
Lines 155-160 Link Here
155
	done
155
	done
156
}
156
}
157
157
158
# add forth parameter to pickup btrfs subvol info
158
parsefstab () {
159
parsefstab () {
159
	while read -r line; do
160
	while read -r line; do
160
		case "$line" in
161
		case "$line" in
Lines 165-176 Link Here
165
				set -f
166
				set -f
166
				set -- $line
167
				set -- $line
167
				set +f
168
				set +f
168
				printf '%s %s %s\n' "$1" "$2" "$3"
169
				printf '%s %s %s %s\n' "$1" "$2" "$3" "$4"
169
			;;
170
			;;
170
		esac
171
		esac
171
	done
172
	done
172
}
173
}
173
174
175
#check_btrfs_mounted $bootsv $bootuuid)
176
check_btrfs_mounted () {
177
	bootsv="$1"
178
	bootuuid="$2"
179
	bootdev=$(blkid | grep "$bootuuid" | cut -d ':' -f  1)
180
	bindfrom=$(grep " btrfs " /proc/self/mountinfo |
181
		   grep " $bootdev " | grep " /$bootsv " | cut -d ' ' -f 5)
182
	printf "%s" "$bindfrom"
183
}
184
174
unescape_mount () {
185
unescape_mount () {
175
	printf %s "$1" | \
186
	printf %s "$1" | \
176
		sed 's/\\011/	/g; s/\\012/\n/g; s/\\040/ /g; s/\\134/\\/g'
187
		sed 's/\\011/	/g; s/\\012/\n/g; s/\\040/ /g; s/\\134/\\/g'
177
-- a/linux-boot-prober
188
++ b/linux-boot-prober
Lines 5-20 Link Here
5
5
6
newns "$@"
6
newns "$@"
7
require_tmpdir
7
require_tmpdir
8
ERR="n"
9
10
tmpmnt=/var/lib/os-prober/mount
11
if [ ! -d "$tmpmnt" ]; then
12
	mkdir "$tmpmnt"
13
fi
14
15
mounted=
16
bootmnt=
17
bootsv=
18
bootuuid=
8
19
9
grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true
20
grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true
10
21
11
partition="$1"
22
if [ -z "$1" ]; then
23
	ERR=y
24
elif [ "$1" = btrfs -a -z "$2" ]; then
25
	ERR=y
26
elif [ "$1" = btrfs -a -z "$3" ]; then
27
	ERR=y
28
elif [ "$1" = btrfs ]; then
29
	type=btrfs
30
	echo "$2" | grep -q "^UUID=" || ERR=y
31
	echo "$3" | grep -q "^subvol=" || ERR=y
32
	export "$2"
33
	export "$3"
34
	partition=$(blkid | grep "$UUID" | cut -d ':' -f 1 | tr '\n' ' ' | cut -d ' ' -f 1)
35
	debug "btrfs: partition=$partition, UUID=$UUID, subvol=$subvol"
36
else
37
	partition="$1"
38
	type=other
39
fi
12
40
13
if [ -z "$partition" ]; then
41
if [ "x$ERR" != xn ]; then
14
	echo "usage: linux-boot-prober partition" >&2
42
	echo "usage: linux-boot-prober partition" >&2
43
	echo "       linux-boot-prober partition | btrfs UUID=<> subvol=<>" >&2
15
	exit 1
44
	exit 1
16
fi
45
fi
17
46
47
if [ "$type" = btrfs ]; then
48
	# handle all of the btrfs stuff here
49
	if [ ! -e "/proc/self/mountinfo" ]; then
50
		warn "/proc/self/mountinfo does not exist, exiting"
51
		umount "$tmpmnt" 2>/dev/null
52
		rmdir "$tmpmnt" 2>/dev/null
53
		exit 1
54
	fi
55
	mpoint=$(grep "btrfs" /proc/self/mountinfo | grep " /$subvol " | grep " $partition " | cut -d ' ' -f 5)
56
	if [ "$mpoint" = "/" ]; then
57
		warn "specifying active root not valid, exiting"
58
		umount "$tmpmnt" 2>/dev/null
59
		rmdir "$tmpmnt" 2>/dev/null
60
		exit 1
61
	fi
62
	if [ "$mpoint" = "$tmpmnt" ]; then
63
		warn "btrfs subvol=$subvool, UUID=$UUID, already mounted on $tmpmnt **ERROR**"
64
		umount "$tmpmnt" 2>/dev/null
65
		rmdir "$tmpmnt" 2>/dev/null
66
		exit 1
67
	fi
68
	if [ -z "$mpoint" ]; then
69
		# mount the btrfs root
70
		if ! mount -o subvol=$subvol -t btrfs -U $UUID "$tmpmnt" 2>/dev/null; then
71
			warn "error mounting btrfs subvol=$subvol UUID=$UUID"
72
			umount "$tmpmnt/boot" 2>/dev/null
73
			umount "$tmpmnt" 2>/dev/null
74
			rmdir "$tmpmnt" 2>/dev/null
75
			exit 1
76
		fi
77
	else
78
		# bind-mount
79
		if ! mount -o bind "$mpoint" "$tmpmnt" 2>/dev/null; then
80
			warn "error mounting btrfs bindfrom=$mpoint subvol=$subvol UUID=$UUID"
81
			umount "$tmpmnt/boot" 2>/dev/null
82
			umount "$tmpmnt" 2>/dev/null
83
			rmdir "$tmpmnt" 2>/dev/null
84
			exit 1
85
		fi
86
	fi
87
	debug "mounted btrfs $partition, subvol=$subvol on $tmpmnt"
88
	if [ ! -e "$tmpmnt/etc/fstab" ]; then
89
		warn "btrfs subvol=$subvol not root"
90
		umount "$tmpmnt" 2>/dev/null
91
		rmdir "$tmpmnt" 2>/dev/null
92
		exit 1
93
	fi
94
	bootmnt=$(parsefstab < "$tmpmnt/etc/fstab" | grep " /boot ") || true
95
	if [ -z "$bootmnt" ]; then
96
		# /boot is part of the root
97
		bootpart="$partition"
98
		bootsv="$subvol"
99
	elif echo "$bootmnt" | cut -d ' ' -f 3 | grep -q "btrfs"; then
100
		# separate btrfs /boot subvolume
101
		bootsv=$(echo "$bootmnt" | cut -d ' ' -f 4 | grep "^subvol=" | sed "s/subvol=//" )
102
		bootuuid=$(echo "$bootmnt" | cut -d ' ' -f 1 | grep "^UUID=" | sed "s/UUID=//" )
103
		debug "mounting btrfs $tmpmnt/boot UUID=$bootuuid subvol=$bootsv"
104
		bindfrom=$(check_btrfs_mounted $bootsv $bootuuid)
105
		if [ -n "$bindfrom" ]; then
106
			# already mounted some place
107
			if ! mount -o bind $bindfrom "$tmpmnt/boot" 2>/dev/null; then
108
				warn "error bind mounting btrfs boot subvol=$bootsv, from=$bindfrom"
109
				umount "$tmpmnt/boot" 2>/dev/null
110
				umount "$tmpmnt" 2>/dev/null
111
				rmdir "$tmpmnt" 2>/dev/null
112
				exit 1
113
			fi
114
		elif ! mount -o subvol=$bootsv -t btrfs -U $bootuuid "$tmpmnt/boot" 2>/dev/null; then
115
			warn "error mounting btrfs boot partition subvol=$bootsv, UUID=$bootuuid"
116
			umount "$tmpmnt/boot" 2>/dev/null
117
			umount "$tmpmnt" 2>/dev/null
118
			rmdir "$tmpmnt" 2>/dev/null
119
			exit 1
120
		fi
121
		bootpart=$(grep " btrfs " /proc/self/mountinfo | grep " /$bootsv " | cut -d ' ' -f 10)
122
	else
123
		# non-btrfs partition or logical volume
124
		linux_mount_boot $partition $tmpmnt
125
		bootpart="${mountboot%% *}"
126
		bootsv=
127
	fi
128
129
	test="/usr/lib/linux-boot-probes/mounted/40grub2"
130
	if [ -f $test ] && [ -x $test ]; then
131
		debug "running $test $partition $bootpart $tmpmnt $type $subvol $bootsv"
132
		if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvol" "$bootsv"; then
133
			debug "$test succeeded"
134
		fi
135
	fi
136
	umount "$tmpmnt/boot" 2>/dev/null || true
137
	if ! umount "$tmpmnt" 2>/dev/null; then
138
		warn "problem umount $tmpmnt"
139
	fi
140
	rmdir "$tmpmnt" 2>/dev/null || true
141
142
	exit 0
143
fi
144
18
if ! mapped="$(mapdevfs "$partition")"; then
145
if ! mapped="$(mapdevfs "$partition")"; then
19
	log "Device '$partition' does not exist; skipping"
146
	log "Device '$partition' does not exist; skipping"
20
	continue
147
	continue
21
-- a/linux-boot-probes/mounted/common/40grub2
148
++ b/linux-boot-probes/mounted/common/40grub2
Lines 2-18 Link Here
2
. /usr/share/os-prober/common.sh
2
. /usr/share/os-prober/common.sh
3
set -e
3
set -e
4
4
5
# add support for btrfs with no separate /boot
6
# that is, rootsv = bootsv
5
partition="$1"
7
partition="$1"
6
bootpart="$2"
8
bootpart="$2"
7
mpoint="$3"
9
mpoint="$3"
8
type="$4"
10
type="$4"
11
rootsv="$5"
12
bootsv="$6"
9
13
10
found_item=0
14
found_item=0
11
15
12
entry_result () {
16
entry_result () {
17
	if [ "x$type" = "xbtrfs" ]; then
18
		bsv=${bootsv:+/}${bootsv}
19
		# if path is not relative to subvolume make it relative
20
		kernel=${kernel#${bsv}}
21
		kernelfile=$kernel
22
		initrd=${initrd#${bsv}}
23
		if [ "x$GRUB_FS" != "xbtrfs" ]; then
24
		    # absolute path needed: prepend subvolume if $kernel isn't empty
25
		    kernel=${kernel:+${bsv}}${kernel}
26
		    initrd=${initrd:+${bsv}}${initrd}
27
		fi
28
		# assumed: rootsv != bootsv if rootsv isn't ancestor of bootsv
29
		[ "$partition" != "$bootpart" -o "$rootsv" != "$bootsv" ] && kernelfile="/boot${kernelfile}"
30
	else
31
		kernelfile=$kernel
32
	fi
13
	if [ "$ignore_item" = 0 ] && \
33
	if [ "$ignore_item" = 0 ] && \
14
	   [ -n "$kernel" ] && \
34
	   [ -n "$kernel" ] && \
15
	   [ -e "$mpoint/$kernel" ]; then
35
	   [ -e "$mpoint/$kernelfile" ]; then
16
		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
36
		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
17
		found_item=1
37
		found_item=1
18
	fi
38
	fi
Lines 64-70 Link Here
64
					ignore_item=1
84
					ignore_item=1
65
				fi
85
				fi
66
			;;
86
			;;
67
			linux)
87
			linux|linuxefi|linux16)
68
				# Hack alert: sed off any (hdn,n) but
88
				# Hack alert: sed off any (hdn,n) but
69
				# assume the kernel is on the same
89
				# assume the kernel is on the same
70
				# partition.
90
				# partition.
Lines 73-86 Link Here
73
				parameters="$@"
93
				parameters="$@"
74
				# Systems with a separate /boot will not have
94
				# Systems with a separate /boot will not have
75
				# the path to the kernel in grub.cfg.
95
				# the path to the kernel in grub.cfg.
76
				if [ "$partition" != "$bootpart" ]; then
96
				if [ "$partition" != "$bootpart" -a "$type" != "btrfs" ]; then
77
					kernel="/boot$kernel"
97
					kernel="/boot$kernel"
78
				fi
98
				fi
79
			;;
99
			;;
80
			initrd)
100
			initrd|initrdefi|initrd16)
81
				initrd="$(echo "$2" | sed 's/(.*)//')"
101
				initrd="$(echo "$2" | sed 's/(.*)//')"
82
				# Initrd same.
102
				# Initrd same.
83
				if [ "$partition" != "$bootpart" ]; then
103
				if [ "$partition" != "$bootpart" -a "$type" != "btrfs" ]; then
84
					initrd="/boot$initrd"
104
					initrd="/boot$initrd"
85
				fi
105
				fi
86
			;;
106
			;;
87
-- a/os-prober
107
++ b/os-prober
Lines 79-84 Link Here
79
		echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name |
79
		echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name |
80
			sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|")"
80
			sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|")"
81
	fi
81
	fi
82
83
	# now lets make sure we got all of the btrfs partitions and disks
84
	blkid | grep btrfs | cut -d ':' -f 1
82
}
85
}
83
86
84
parse_proc_swaps () {
87
parse_proc_swaps () {
Lines 136-141 Link Here
136
	grep "^md" /proc/mdstat | cut -d: -f2- | parse_proc_mdstat >"$OS_PROBER_TMP/raided-map" || true
139
	grep "^md" /proc/mdstat | cut -d: -f2- | parse_proc_mdstat >"$OS_PROBER_TMP/raided-map" || true
137
fi
140
fi
138
141
142
: >"$OS_PROBER_TMP/btrfs-vols"
143
139
for partition in $(partitions); do
144
for partition in $(partitions); do
140
	if ! mapped="$(mapdevfs "$partition")"; then
145
	if ! mapped="$(mapdevfs "$partition")"; then
141
		log "Device '$partition' does not exist; skipping"
146
		log "Device '$partition' does not exist; skipping"
Lines 154-160 Link Here
154
		continue
159
		continue
155
	fi
160
	fi
156
161
157
	if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
162
	# do btrfs processing here; both mounted and unmounted will
163
	# be handled by 50mounted-tests so we can do a subvol only once.
164
	type=$(blkid -o value -s TYPE $mapped || true)
165
	if [ "$type" = btrfs ]; then
166
		uuid=$(blkid -o value -s UUID $mapped)
167
		if grep -q "^$uuid" "$OS_PROBER_TMP/btrfs-vols" ; then
168
			continue
169
		fi
170
		debug "btrfs volume uuid=$uuid partition=$partition"
171
		echo "$uuid" >>"$OS_PROBER_TMP/btrfs-vols"
172
		test="/usr/lib/os-probes/50mounted-tests"
173
		if [ -f "$test" ] && [ -x "$test" ]; then
174
			debug "running $test on btrfs $partition"
175
			if "$test" btrfs "$uuid" "$partition"; then
176
				debug "os detected by $test"
177
		   		continue
178
			fi
179
		fi
180
181
	elif ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
158
		for test in /usr/lib/os-probes/*; do
182
		for test in /usr/lib/os-probes/*; do
159
			if [ -f "$test" ] && [ -x "$test" ]; then
183
			if [ -f "$test" ] && [ -x "$test" ]; then
160
				debug "running $test on $partition"
184
				debug "running $test on $partition"
161
-- a/os-probes/common/50mounted-tests
185
++ b/os-probes/common/50mounted-tests
Lines 14-20 Link Here
14
	rmdir "$tmpmnt" || true
14
	rmdir "$tmpmnt" || true
15
}
15
}
16
16
17
types="$(fs_type "$partition")"
17
if [ "x$1" = xbtrfs ]; then
18
       types=btrfs
19
       if [ -z "$2" -o -z "$3" ]; then
20
               debug "missing btrfs parameters, exiting"
21
               exit 1
22
       fi
23
       UUID="$2"
24
       BTRFSDEV="$3"
25
else
26
       partition="$1"
27
       types="$(fs_type "$partition")"
28
fi
29
18
if [ "$types" = NOT-DETECTED ]; then
30
if [ "$types" = NOT-DETECTED ]; then
19
	debug "$1 type not recognised; skipping"
31
	debug "$1 type not recognised; skipping"
20
	exit 0
32
	exit 0
Lines 58-64 Link Here
58
fi
70
fi
59
71
60
mounted=
72
mounted=
61
if type grub-mount >/dev/null 2>&1 && \
73
74
# all btrfs processing here.  Handle both unmounted and
75
# mounted subvolumes.
76
if [ "$types" = btrfs ]; then
77
	partition="$BTRFSDEV"
78
	debug "begin btrfs processing for $UUID"
79
	# note that the btrfs volume must not be mounted ro
80
	if mount -t btrfs -U "$UUID" "$tmpmnt"  2>/dev/null; then
81
		debug "btrfs volume $UUID mounted"
82
	else
83
		warn "cannot mount btrfs volume $UUID, exiting"
84
		rmdir "$tmpmnt" || true
85
		exit 1
86
	fi
87
88
	if type btrfs >/dev/null 2>&1; then
89
		# besides regular subvols, get ro and snapshot so thet can be excluded
90
		subvols=$(btrfs subvolume list -a "$tmpmnt" | cut -d ' ' -f 9 | sed -e s!^\<FS_TREE\>/!!)
91
		rosubvols=$(btrfs subvolume list -r -a "$tmpmnt" | cut -d ' ' -f 9 | sed -e s!^\<FS_TREE\>/!!)
92
		sssubvols=$(btrfs subvolume list -s -a "$tmpmnt" | cut -d ' ' -f 14 | sed -e s!^\<FS_TREE\>/!!)
93
	else
94
		subvols=""
95
		rosubvols=""
96
		sssubvols=""
97
		defaultvol=""
98
	fi
99
100
        defaultvol=$(btrfs subvolume get-default "$tmpmnt" | cut -d ' ' -f 9)
101
        if ! umount "$tmpmnt"; then
102
            warn "failed to umount btrfs volume on $tmpmnt"
103
            rmdir "$tmpmnt" || true
104
            exit 1
105
        fi
106
	if [ -z "$subvols" ]; then
107
		debug "no subvols found on btrfs volume $UUID"
108
		exit 1
109
	fi
110
	found=
111
        for subvol in $subvols; do
112
		debug "begin btrfs processing for $UUID subvol=$subvol"
113
		if [ "$subvol" != "$defaultvol" ]; then
114
			if echo "$rosubvols" | grep -q -x "$subvol"; then
115
				continue
116
			fi
117
			if echo "$sssubvols" | grep -q -x "$subvol"; then
118
				continue
119
			fi
120
		fi
121
		mounted=
122
		mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | grep "/$subvol " | cut -d ' ' -f 5)"
123
		if [ -n "$mpoint" ]; then
124
			if [ "x$mpoint" = "x/" ]; then
125
				continue # this is the root for the running system
126
			fi
127
			mounted=1
128
		else
129
			# again, do not mount btrfs ro
130
			mount -t btrfs -o subvol="$subvol" -U "$UUID" "$tmpmnt"
131
			mpoint="$tmpmnt"
132
		fi
133
		test="/usr/lib/os-probes/mounted/90linux-distro"
134
		if [ -f "$test" ] && [ -x "$test" ]; then
135
			debug "running subtest $test"
136
			if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID" "subvol=$subvol"; then
137
				debug "os found by subtest $test on subvol $subvol"
138
				found=1
139
			fi
140
		fi
141
		if [ -z "$mounted" ]; then
142
			if ! umount "$tmpmnt"; then
143
			    warn "failed to umount $tmpmnt"
144
			fi
145
		fi
146
	done
147
	rmdir "$tmpmnt" || true
148
	if [ "$found" ]; then
149
		exit 0
150
	else
151
		exit 1
152
	fi
153
elif type grub-mount >/dev/null 2>&1 && \
62
   type grub-probe >/dev/null 2>&1 && \
154
   type grub-probe >/dev/null 2>&1 && \
63
   grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
155
   grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
64
	mounted=1
156
	mounted=1
Lines 83-89 Link Here
83
		fi
175
		fi
84
	done
176
	done
85
fi
177
fi
86
do_unmount
178
179
if [ "$types" != "btrfs" ]; then
180
	do_unmount
181
fi
87
182
88
# No tests found anything.
183
# No tests found anything.
89
exit 1
184
exit 1
90
-- a/os-probes/mounted/common/90linux-distro
185
++ b/os-probes/mounted/common/90linux-distro
Lines 7-12 Link Here
7
partition="$1"
7
partition="$1"
8
dir="$2"
8
dir="$2"
9
type="$3"
9
type="$3"
10
uuid="$4"
11
subvol="$5"
10
12
11
# This test is inaccurate, but given separate / and /boot partitions and the
13
# This test is inaccurate, but given separate / and /boot partitions and the
12
# fact that only some architectures have ld-linux.so, I can't see anything
14
# fact that only some architectures have ld-linux.so, I can't see anything
Lines 143-149 Link Here
143
	fi
145
	fi
144
	
146
	
145
        label="$(count_next_label "$short")"
147
        label="$(count_next_label "$short")"
146
	result "$partition:$long:$label:linux"
148
	if [ "x$type" = "xbtrfs" -a "x$uuid" != "x" -a "x$subvol" != "x" ]; then
149
		result "$partition:$long:$label:linux:$type:$uuid:$subvol"
150
	else
151
		result "$partition:$long:$label:linux"
152
	fi
147
	exit 0
153
	exit 0
148
else
154
else
149
	exit 1
155
	exit 1
150
-- a/README.btrfs
156
++ b/README.btrfs
Line 0 Link Here
1
BTRFS is a new filesystem which combines the filesystem with logical volume
2
management (subvolumes).  For further information, see:
3
      https://btrfs.wiki.kernel.org/index.php/Main_Page
4
      https://btrfs.wiki.kernel.org/index.php/FAQ
5
6
In order to support BTRFS, a number of changes were necessary to os-prober,
7
os-probes/common/50mounted-tests, os-probes/mounted/common/90linux-distro,
8
linux-boot-prober, and linux-boot-probes/common/50mounted-tests.
9
10
The biggest impact will be to grub2 where there is additional information
11
output by os-prober and where, if a BTRFS subvolume is being used for root,
12
the parameters for linux-boot-prober have changed.
13
14
Sun 30 Dec 2012 11:49:52 AM EST Gene Czarcinski <gene@czarc.net>
15

Return to bug 817905