[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH] adding raid5 support, plus a bugfix



[Please CC me on replies - I'm not currently subscribed to -boot. That
might change if I start to do d-i hacking more frequently.]

Hi d-i team,

After a discussion with joeyh and joshk last night on #debian-boot, I
submit to you the attached patch for inclusion in d-i. It adds RAID5
support, plus fixes a couple of trivial but important bugs in the RAID1
code's check for the required number of partitions to build the array. I
tried my code in a vmware virtual machine and it works there. The only
real rough spot in my code is where I try to ensure that there be at
least 3 active partitions, as required by RAID5. (I didn't actually see
any such limitation in the mdadm man page, but that seems to be the case
based on what I have heard about RAID5. Maybe mdadm allows for some sort
of partial or degraded performance with fewer? Anyone know for sure?) I
was able to select fewer than 3 active partitions and be allowed to
continue with the raid config. Depending on the particular demands of
mdadm that might need to be fixed, but other than that my code Works For
Me(tm).

(BTW: I have a similar question about what it means for mdadm to allow
RAID1 with anything other than exactly 2 active partitions. Should this
be enforced as well?)

- Jimmy Kaplowitz
jimmy@debian.org
Index: mdcfg/debian/mdcfg-utils.templates
===================================================================
--- mdcfg/debian/mdcfg-utils.templates	(revision 22253)
+++ mdcfg/debian/mdcfg-utils.templates	(working copy)
@@ -36,7 +36,7 @@
 
 Template: mdcfg/createmain
 Type: select
-__Choices: RAID0, RAID1, Cancel
+__Choices: RAID0, RAID1, RAID5, Cancel
 _Description: Multidisk device type:
  Please choose the type of the multidisk device to be created.
 
@@ -64,6 +64,31 @@
  devices, the remaining partitions will be added to the array as "missing".
  You will be able to add them later to the array.
 
+Template: mdcfg/raid5devcount
+Type: string
+_Description: Number of active devices for the RAID5 array:
+ The RAID5 array will consist of both active and spare partitions. The active
+ partitions are those used, while the spare devices will only be used if one or
+ more of the active devices fail. A minimum of three active devices is
+ required.
+ .
+ NOTE: this setting cannot be changed later.
+
+Template: mdcfg/raid5sparecount
+Type: string
+_Description: Number of spare devices for the RAID5 array:
+
+Template: mdcfg/raid5sparedevs
+Type: multiselect
+Choices: ${PARTITIONS}
+_Description: Spare devices for the RAID5 multidisk device:
+ You have chosen to create an RAID5 array with ${COUNT} spare devices.
+ .
+ Please choose which partitions will be used as spare devices.
+ You may choose up to ${COUNT} partitions. If you choose less than ${COUNT}
+ devices, the remaining partitions will be added to the array as "missing".
+ You will be able to add them later to the array.
+
 Template: mdcfg/raid0devs
 Type: multiselect
 Choices: ${PARTITIONS}
@@ -80,6 +105,15 @@
  Please choose which partitions are active devices.
  You must select exactly ${COUNT} partitions.
 
+Template: mdcfg/raid5devs
+Type: multiselect
+Choices: ${PARTITIONS}
+_Description: Active devices for the RAID5 multidisk device:
+ You have chosen to create an RAID5 array with ${COUNT} active devices.
+ .
+ Please choose which partitions are active devices.
+ You must select exactly ${COUNT} partitions.
+
 Template: mdcfg/deletemenu
 Type: select
 __Choices: ${DEVICES}, Cancel
Index: mdcfg/mdcfg.sh
===================================================================
--- mdcfg/mdcfg.sh	(revision 22253)
+++ mdcfg/mdcfg.sh	(working copy)
@@ -77,6 +77,8 @@
 		get_partitions
 
 		case $RET in
+			"RAID5")
+			md_create_raid5;;
 			"RAID1")
 			md_create_raid1;;
 			"RAID0")
@@ -220,9 +222,9 @@
 	db_get mdcfg/raid1sparecount
 	SPARE_COUNT="${RET}"
 	REQUIRED=$(($DEV_COUNT + $SPARE_COUNT))
-	if [ "$DEV_COUNT" -gt "$NUM_PART" ] ; then
+	if [ "$REQUIRED" -gt "$NUM_PART" ] ; then
 		db_subst mdcfg/notenoughparts NUM_PART "${NUM_PART}"
-		db_subst mdcfg/notenoughparts REQUIRED "${DEV_COUNT}"
+		db_subst mdcfg/notenoughparts REQUIRED "${REQUIRED}"
 		db_input critical mdcfg/notenoughparts
 		db_go mdcfg/notenoughparts
 		return
@@ -311,6 +313,146 @@
 	`mdadm --create /dev/md/${MD_NUM} --force -R -l raid1 -n ${DEV_COUNT} -x ${SPARE_COUNT} ${RAID_DEVICES} ${SPARE_DEVICES} ${MISSING_SPARES}`
 }
 
+md_create_raid5() {
+	OK=0
+
+	db_set mdcfg/raid5devcount "3"
+
+	# Get the count of active devices
+	while [ "${OK}" -eq 0 ]; do
+		db_input critical mdcfg/raid5devcount
+		db_go
+		if [ "$?" -eq "30" ]; then
+			# If the user has pressed "Cancel", return
+			return
+		fi
+
+		# Figure out, if the user entered a number
+		db_get mdcfg/raid5devcount
+		RET=`echo ${RET}|sed -e "s/[[:space:]]//g"`
+		if [ ! -z "${RET}" ]; then
+			let "OK=${RET}>0 && ${RET}<99"
+		fi
+	done
+
+	db_set mdcfg/raid5sparecount "0"
+	OK=0
+
+	# Same procedure as above, but get the number of spare partitions
+	# this time.
+	# TODO: Make a general function for this kind of stuff
+	while [ "${OK}" -eq 0 ]; do
+		db_input critical mdcfg/raid5sparecount
+		db_go
+		if [ "$?" -eq "30" ]; then
+			return
+		fi
+		db_get mdcfg/raid5sparecount
+		RET=`echo ${RET}|sed -e "s/[[:space:]]//g"`
+		if [ ! -z "${RET}" ]; then
+			let "OK=${RET}>=0 && ${RET}<99"
+		fi
+	done
+
+	db_get mdcfg/raid5devcount
+	DEV_COUNT="${RET}"
+	if [ "$DEV_COUNT" -lt 3 ] ; then
+		DEV_COUNT=3 # Minimum number for RAID5
+	fi
+	db_get mdcfg/raid5sparecount
+	SPARE_COUNT="${RET}"
+	REQUIRED=$(($DEV_COUNT + $SPARE_COUNT))
+	if [ "$REQUIRED" -gt "$NUM_PART" ] ; then
+		db_subst mdcfg/notenoughparts NUM_PART "${NUM_PART}"
+		db_subst mdcfg/notenoughparts REQUIRED "${REQUIRED}"
+		db_input critical mdcfg/notenoughparts
+		db_go mdcfg/notenoughparts
+		return
+	fi
+
+	db_set mdcfg/raid5devs ""
+	SELECTED=0
+
+	# Loop until the correct amount of active devices has been selected
+	while [ "${SELECTED}" -ne "${DEV_COUNT}" ]; do
+		db_subst mdcfg/raid5devs COUNT "${DEV_COUNT}"
+		db_subst mdcfg/raid5devs PARTITIONS "${PARTITIONS}"
+		db_input critical mdcfg/raid5devs
+		db_go
+		if [ "$?" -eq "30" ]; then
+			return
+		fi
+
+		db_get mdcfg/raid5devs
+		SELECTED=0
+		for i in $RET; do
+			DEVICE=`echo ${i}|sed -e "s/,//"`
+			let SELECTED++
+		done
+	done
+
+	# Remove partitions selected in raid5devs from the PARTITION list
+	db_get mdcfg/raid5devs
+
+	prune_partitions "$RET"
+
+	db_set mdcfg/raid5sparedevs ""
+	SELECTED=0
+	if [ "${SPARE_COUNT}" -gt 0 ]; then  
+		FIRST=1
+		# Loop until the correct amount of devices has been selected.
+	  # That means any number less than or equal to the spare count
+		while [ "${SELECTED}" -gt "${SPARE_COUNT}" -o "${FIRST}" -eq 1 ]; do
+			FIRST=0
+			db_subst mdcfg/raid5sparedevs COUNT "${SPARE_COUNT}"
+			db_subst mdcfg/raid5sparedevs PARTITIONS "${PARTITIONS}"
+			db_input critical mdcfg/raid5sparedevs
+			db_go
+			if [ "$?" -eq "30" ]; then
+				return
+			fi
+	
+			db_get mdcfg/raid5sparedevs
+			SELECTED=0
+			for i in $RET; do
+				DEVICE=`echo ${i}|sed -e "s/,//"`
+				let SELECTED++
+			done
+		done
+	fi
+
+	# The amount of spares, the user has selected
+	NAMED_SPARES=${SELECTED}
+
+	db_get mdcfg/raid5devs
+	RAID_DEVICES=`echo ${RET}|sed -e "s/,//g"`
+
+	db_get mdcfg/raid5sparedevs
+	SPARE_DEVICES=`echo ${RET}|sed -e "s/,//g"`
+
+	MISSING_SPARES=""
+
+	COUNT=${NAMED_SPARES}
+	while [ "${COUNT}" -lt "${SPARE_COUNT}" ]; do
+		MISSING_SPARES="${MISSING_SPARES} missing"
+		let COUNT++
+	done
+
+	# Find the next available md-number
+	MD_NUM=`grep ^md /proc/mdstat|sed -e 's/^md\(.*\) : active .*/\1/'|sort|tail -n 1`
+	if [ -z "${MD_NUM}" ]; then
+		MD_NUM=0
+	else
+		let MD_NUM++
+	fi
+
+	echo "Selected spare count: ${NAMED_SPARES}"
+	echo "Raid devices count: ${DEV_COUNT}"
+	echo "Spare devices count: ${SPARE_COUNT}"
+	echo "Commandline:"
+	`mdadm --create /dev/md/${MD_NUM} --force -R -l raid5 -n ${DEV_COUNT} -x ${SPARE_COUNT} ${RAID_DEVICES} ${SPARE_DEVICES} ${MISSING_SPARES}`
+}
+
 md_mainmenu() {
 	while [ 1 ]; do
 		db_set mdcfg/mainmenu "false"
@@ -334,11 +476,12 @@
 ### Main of script ###
 
 # Try to load the necesarry modules.
-# Supported schemes: RAID 0, RAID 1
+# Supported schemes: RAID 0, RAID 1, RAID 5
 depmod -a 1>/dev/null 2>&1
 modprobe md 1>/dev/null 2>&1
 modprobe raid0 >/dev/null 2>&1
 modprobe raid1 1>/dev/null 2>&1
+modprobe raid5 >/dev/null 2>&1
 
 # Try to detect MD devices, and start them
 /sbin/mdrun

Attachment: signature.asc
Description: Digital signature


Reply to: