File: md-base.sh

package info (click to toggle)
partman-md 77
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,744 kB
  • ctags: 23
  • sloc: sh: 774; makefile: 2
file content (229 lines) | stat: -rw-r--r-- 4,867 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
. /lib/partman/lib/base.sh

# Translate device from /proc/mdstat (mdX) to device node
md_devnode () {
	local num=$(echo $1 | sed -e "s/^md//")

	# Also handle the case where the first does not exist
	if [ -b /dev/md/$num ]; then
		echo /dev/md/$num
	elif [ -b /dev/md$num ]; then
		echo /dev/md$num
	else
		return 1
	fi
}

# Device node to use at creation time.  This is a bit nasty as it differs
# between mdadm metadata formats, and the only way to find out the default
# seems to be to check mdadm's version (otherwise we break installation of
# older releases).
md_devnode_create () {
	if mdadm -V 2>&1 | egrep -q '^mdadm - v([012]|3\.0)'; then
		echo "/dev/md$1"
	else
		echo "/dev/md/$1"
	fi
}

# Would this partition be allowed as a RAID physical volume?
md_allowed () {
	local dev=$1
	local id=$2

	cd $dev

	# sparc can not have RAID starting at 0 or it will destroy the partition table
	if [ "$(udpkg --print-architecture)" = sparc ] && \
	   [ "${id%%-*}" = "0" ]; then
		return 1
	fi

	local md=no
	local fs
	open_dialog PARTITION_INFO $id
	read_line x1 x2 size x4 fs x6 x7
	close_dialog
	if [ "$fs" = free ]; then
		# parted can't deal with VALID_FLAGS on free space as yet,
		# so unfortunately we have to special-case label types.
		local label
		open_dialog GET_LABEL_TYPE
		read_line label
		close_dialog
		case $label in
		    amiga|bsd|dasd|gpt|mac|msdos|sun)
			# ... by creating a partition
			md=yes
			;;
		esac
	else
		local flag
		open_dialog VALID_FLAGS $id
		while { read_line flag; [ "$flag" ]; }; do
			if [ "$flag" = raid ]; then
				md=yes
			fi
		done
		close_dialog
	fi

	# Don't list devices that are too small (less than 1MB),
	# they're most likely alignment artifacts
	if [ $size -lt 1048576 ]; then
		md=no
	fi

	[ $md = yes ]
}

md_list_allowed () {
	partman_list_allowed md_allowed
}

md_list_allowed_free () {
	local line

	IFS="$NL"
	for line in $(md_list_allowed); do
		restore_ifs
		local dev="${line%%$TAB*}"
		local rest="${line#*$TAB}"
		local id="${rest%%$TAB*}"
		if [ -e "$dev/locked" ] || [ -e "$dev/$id/locked" ]; then
			continue
		fi
		local path="${line##*$TAB}"
		if [ ! -e "$path" ]; then
			echo "$line"
		else
			local mappedpath="$(mapdevfs "$path")"
			# Exclude partitions that are already part of a RAID
			# set
			if ! egrep -q "(${path#/dev/}|${mappedpath#/dev/})" /proc/mdstat; then
				echo "$line"
			fi
		fi
		IFS="$NL"
	done
	restore_ifs
}

# Prepare a partition for use as a RAID physical volume. If this returns
# true, then it did some work and a commit is necessary. Prints the new
# path.
md_prepare () {
	local dev="$1"
	local id="$2"
	local size parttype fs path

	cd "$dev"
	open_dialog PARTITION_INFO "$id"
	read_line x1 id size freetype fs path x7
	close_dialog

	if [ "$fs" = free ]; then
		local newtype

		case $freetype in
		    primary)
			newtype=primary
			;;
		    logical)
			newtype=logical
			;;
		    pri/log)
			local parttype
			open_dialog PARTITIONS
			while { read_line x1 x2 x3 parttype x5 x6 x7; [ "$parttype" ]; }; do
				if [ "$parttype" = primary ]; then
					has_primary=yes
				fi
			done
			close_dialog
			if [ "$has_primary" = yes ]; then
				newtype=logical
			else
				newtype=primary
			fi
			;;
		esac

		open_dialog NEW_PARTITION $newtype ext2 $id full $size
		read_line x1 id x3 x4 x5 path x7
		close_dialog
	fi

	mkdir -p "$id"
	local method="$(cat "$id/method" 2>/dev/null || true)"
	if [ "$method" = swap ]; then
		disable_swap "$dev" "$id"
	fi
	if [ "$method" != raid ]; then
		echo raid >"$id/method"
		rm -f "$id/use_filesystem"
		rm -f "$id/format"
		update_partition "$dev" "$id"
		echo "$path"
		return 0
	fi

	echo "$path"
	return 1
}

md_get_level () {
	echo $(mdadm -Q --detail $1 | grep "Raid Level" | sed "s/.*: //")
}

md_get_devices () {
	local device
	MD_DEVICES=""
	for device in $(grep ^md /proc/mdstat | \
			sed -e 's/^\(md.*\) : .*/\1/'); do
		local mddev=$(md_devnode $device) || return 1
		local mdtype=$(md_get_level $mddev)
		MD_DEVICES="${MD_DEVICES:+$MD_DEVICES, }${device}_$mdtype"
	done
}

md_db_get_number () {
	local question="$1"
	local min="$2"
	local max="$3"
	while :; do
		db_input critical "$question"
		db_go || return $?
		db_get "$question"
		# Figure out if the user entered a number
		RET="$(echo "$RET" | sed 's/[[:space:]]//g')"
		if [ "$RET" ] && [ "$RET" -ge "$min" ] && [ "$RET" -le "$max" ]; then
			break
		fi
	done
	return 0
}

# Find the next available MD device number
md_next_device_number () {
	local md_num="$(grep ^md /proc/mdstat | \
			sed -e 's/^md\(.*\) : active .*/\1/' | sort | tail -n1)"
	if [ -z "$md_num" ]; then
		md_num=0
	else
		md_num="$(($md_num + 1))"
	fi
	echo "$md_num"
}

md_lock_devices () {
	local name dev
	name="$1"
	shift

	db_subst partman-md/text/in_use DEVICE "$name"
	db_metaget partman-md/text/in_use description
	for dev; do
		partman_lock_unit "$dev" "$RET"
	done
}