#!/bin/sh # mdrun, (c) Eduard Bloch 2003 # Usage: # Without arguments: autodetect all RAID partitions and activate MDs # Arguments: [ DEVDIR ] NUMBER UUID [ ... ] # a number of number/uuid pairs, where NUMBER is the one from /dev/md/* # Argument: LIST # lists all raids in the syntax needed for the pairs (see above) # IMPORTANT: create /dev/fs directory if you have devfs support in the kernel # but do not want to mount it over /dev. Usage of /dev/fs directory will keep # mdrun away from /dev. # If the first argument is a directory, it will be used as a writeable # temporary directory for device nodes. mdrun needs mknod to create them # on-the-fly # Environment: # MORERAIDVOLUMES (list of strings) : additional raid disks to scan, # eg. loop devices if ! test -e /proc/partitions ; then echo "/proc not mounted!" exit 1 fi DEVDIR=/dev if [ -d "$1" ] ; then AUTOCREATE=true DEVDIR="$1" shift fi # For people that compile the kernel with devfs (means: different # proc/partitions content), but without auto-mounting it if ! uname -r | grep "^2.6" 1>/dev/null && [ -z "$AUTOCREATE" ] && grep " devfs" /proc/filesystems >/dev/null 2>&1 && ! grep "^devfs" /proc/mounts >/dev/null 2>&1 ; then mkdir /dev/fs 2>/dev/null # if we can do it - good, we will use it. Otherwise, use /dev even if it is ugly # mount devfs for now to make the device names match, umount later if [ -d /dev/fs ] ; then DEVDIR=/dev/fs fi mount none $DEVDIR -tdevfs UMNTDEVFS="umount $DEVDIR" fi # arr(array, index): return contents in array[index]; as with Bourne shell # in general, there is no easy way to distinguish between index not # existing and empty string assigned. arr() { sa_i=`arr_index $2`; eval "echo \"\$$1_${sa_i}\""; unset sa_i; } # seterr(array, index, value): assign the given value to array[index]. setarr() { sa_i=`arr_index $2`; eval "$1_${sa_i}=\"$3\""; unset sa_i; } # arr_index(index): make sure the given index is valid for use. arr_index() { echo $1 | sed -e 's/:/_/g' | sed 's;/;_;g'; } BASE=$DEVDIR/md export BASE #devfs test -d $BASE && BASE=$BASE/ next_free_md() { for raidnr in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do if ! mdadm -D $BASE$raidnr >/dev/null 2>&1 ; then echo $BASE$raidnr return 0 fi done return 1 } listpairs() { for NUMBER in `cat /proc/mdstat | grep "^md. : active" | sed -e 's/^md\(.\) :.*/\1/'`; do echo $NUMBER mdadm -D ${BASE}$NUMBER 2>/dev/null |grep UUID | sed 's/.*: \(.*\)/\1/' done } if [ "$1" = LIST ] ; then echo `listpairs` $UMNTDEVFS exit 0 fi DEVDIRESC=$(echo $DEVDIR | sed -e 's!/!\\/!g') if [ "$AUTOCREATE" ] ; then CREATECMD=$(sed -e "s/.*major.*//; s/.*\ \([:0-9:]\+\)\ \+\ \([:0-9:]\+\)\ \+\ [:0-9:]\+\ \+\([:a-z0-9\/:]\+\).*/mknod \3 b \1 \2 ; / ; s/\//_/g" < /proc/partitions) export CREATECMD export DEVDIR # and we need array nodes, of course ( cd $DEVDIR ; eval $CREATECMD ; for x in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ; do mknod ${BASE}$x b 9 $x done ) PARTLIST=$(sed -e "s/.*major.*//; s/.*\ \([:0-9:]\+\)\ \+\ \([:0-9:]\+\)\ \+\ [:0-9:]\+\ \+\([:a-z0-9\/:]\+\).*/DEVDIR\3 /; s/\//_/g ; s/DEVDIR/$DEVDIRESC\//;" < /proc/partitions) else PARTLIST=$(sed -e "s/.*major.*//; s/^[:0-9 :]* \([:a-z:].[:a-z0-9\/:]*\).*/\1/; s/^\([:a-z:].*\)/$DEVDIRESC\/\1/g" < /proc/partitions) fi for SRC in $PARTLIST $MORERAIDVOLUMES ; do SUM=$(mdadm -E $SRC 2>/dev/null | grep UUID | sed 's/.*: \(.*\)/\1/') for x in $SUM; do UUIDS="$UUIDS $SUM" setarr MDS $SUM "`arr MDS $SUM` $SRC" done done if [ "$#" -gt 1 ] ; then NUMBER=${BASE}$1 MD=$2 shift ; shift if [ "`arr MDS $MD`" != "started" ] ; then mdadm -A $NUMBER -f `arr MDS $MD` && setarr MDS $MD "started" # just to be sure ln /dev/md/$NUMBER /dev/md$NUMBER 2>/dev/null fi fi # and process the rest, if it exists # do not touch active arrays #dropactive() { for NUMBER in `cat /proc/mdstat | grep "^md. : active" | sed -e 's/^md\(.\) :.*/\1/'`; do setarr MDS `mdadm -D ${BASE}$NUMBER 2>/dev/null |grep UUID | sed 's/.*: \(.*\)/\1/'` "started" done #} for MD in $UUIDS; do if [ "`arr MDS $MD`" != "started" ] ; then NUMBER=`next_free_md` mdadm -A $NUMBER -f `arr MDS $MD` && setarr MDS $MD "started" # just to be sure ln /dev/md/$NUMBER /dev/md$NUMBER 2>/dev/null fi done $UMNTDEVFS