mdadm/mdrun

148 lines
4.5 KiB
Bash

#!/bin/sh
# mdrun, (c) Eduard Bloch <blade@debian.org> 2003
# Usage:
# Without arguments: autodetect all RAID partitions and activate MDs
# Arguments: [ DEVDIR ] NUMBER UUID [ <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