whitespace cleanup
[mapsector.git] / lib / 10_map_raid.sh
index 919817c..5ab4141 100644 (file)
@@ -5,33 +5,115 @@ detect_raid()
 
 describe_raid()
 {
-    echo "    RAID level 1"
+    echo "    RAID level 1/5"
 }
 
 do_raid()
 {
     local mddevice
     local mdlevel
+    local mdlayout
 
     echo "# $device: RAID detected" 1>&2
 
     mddevice="`mdadm -Q $device | sed -ne 's/.*\(raid[0-9] \/dev\/[^.]*\).*/\1/' -eT -ep`"
 
     if [ -z "$mddevice" ]; then
-       echo "! raid master device for raid componentn device $device not found" 1>&2
-       exit 1
+        echo "! raid master device for raid componentn device $device not found" 1>&2
+        exit 1
     fi
 
     mdlevel="${mddevice% *}"
     mddevice="${mddevice#* }"
-    
+
     echo "device $mddevice md"
     echo "raidlevel $mdlevel"
-    echo "sector $sector"
 
+    case "$mdlevel" in
+        raid1) ;;
+        raid5) do_raid_raid5 $mddevice ;;
+        *)
+            echo "! unsopported raid level $mdlevel" 1>&2
+            exit 1
+            ;;
+    esac
+
+    echo "sector $sector"
     device="$mddevice"
 
     return 1
 }
 
+raid5_leftsymmetric_calc()
+{
+    local ndrives="$1"
+    local drive="$2" # range 0..$ndrives-1
+    local chunk="$3"
+
+    # Algorithm:
+    #
+    # block = chunk / ndrives
+    # blockrow = chunk % ndrives
+    # if blockrow == ndrives-drive-1:
+    #     return 'parity'
+    # else:
+    #     if drive > ndrives-blockrow-1:
+    #         blockrow = blockrow - 1
+    #     return block*ndrives*(ndrives-1) + blockrow*ndrives + drive
+
+    dc  -e "$chunk $ndrives ~ d $ndrives $drive - 1 - [q]sa=a" \
+        -e "d $ndrives r - 1 - $drive [1-]sa<a" \
+        -e "$ndrives * $drive + r $ndrives * $ndrives 1 - * + p"
+}
+
+do_raid_raid5()
+{
+    local mddevice="$1"
+    local mdlayout
+    local mdcalc
+    local mdchunksize
+    local mddrives
+    local mddrive
+    local chunk
+    local mdchunk
+
+    mdlayout="`mdadm -D $mddevice | awk '/Layout :/{print $3}'`"
+    echo "raidlayout $mdlayout"
+    case "$mdlayout" in
+        left-symmetric) mdcalc="raid5_leftsymmetric_calc" ;;
+        *)
+            echo "! unsopported raid layout $mdlayout" 1>&2
+            exit 1
+            ;;
+    esac
+
+    mdchunksize="`mdadm -D $mddevice | awk '/Chunk Size :/{print $4}'`"
+    mdchunksize="`dc -e "${mdchunksize%K} 2 * p"`"
+    mddrives="`mdadm -D $mddevice | awk '/Raid Devices :/{print $4}'`"
+    mddrive="`mdadm -D $mddevice | awk "/${device##*/}"'$/{print $4}'`"
+
+    echo "raiddrives $mddrives"
+    echo "raiddrive $mddrive"
+    echo "chunksize $mdchunksize"
+
+    chunk="`dc -e "$sector $mdchunksize ~ n [ ] n p"`"
+    subsector="${chunk% *}"
+    chunk="${chunk#* }"
+
+    echo "chunk $chunk"
+    echo "subsector $subsector"
+
+    mdchunk="`$mdcalc $mddrives $mddrive $chunk`"
+    if [ -z "$mdchunk" ]; then
+        echo "chunktype parity"
+        echo "! no parity chunk support"
+        exit 1
+    fi
+
+    echo "chunktype data"
+    echo "raidchunk $mdchunk"
+
+    sector="`dc -e "$mdchunk $mdchunksize * $subsector + p"`"
+}
+
 register_mapper "raid"