Multipathing fails to work with more than 256 LUNs

  • 3667525
  • 16-Feb-2007
  • 30-Apr-2012

Environment

Novell SUSE Linux Enterprise Server 9
Novell Open Enterprise Server (Linux based)

Device-mapper multipath I/O is configured.
There are more than 256 LUNs.

Situation

multipathd does not start, or multipathd starts, but does not see all LUNs.

Resolution

  • Ensure that themultipath-tools package is current.
  • Create additional device files for the LUNs.
  • Reboot the system to start using the newly created device files.

Additional Information

On SLES9 and OES/Linux, the device files for SCSI disks and their partitions are created statically by the devs package. This package contains the device files for 256 SCSI disks (/dev/sda through /dev/sdz and /dev/sdaa through /dev/sdiv) and their partitions. When device-mapper multipath I/O needs to be set up for a larger number of SCSI disk devices (LUNs), additional device files need to be created.

The following script creates the device files /dev/sdiw through /dev/sdzz and the device files for the partitions on these disks.

#! /bin/bash
set -e

#########################################################################
# - Code reuse is the sincerest form of flattery.
# Borrowed from /usr/share/doc/packages/devs/makedevs

# makedevs - a script to generate devices
#
# Copyright (c) 1996-2003 SuSE Linux AG, Nuernberg, Germany.
#
# Author: Hubert Mantel , 1996-2002

DEV=/dev
RPM=0

#########################################################################
# Check for root
#########################################################################

if [ "`id | grep uid=0`" = "" ]; then
echo "In order to create device inodes, you must run this script"
echo "as root."
exit 1
fi

if [ ! -d $DEV ]; then
echo "Creating directory $DEV"
mkdir $DEV
fi

#########################################################################
# Create one single device
#########################################################################

function create_dev () {
if [ $# != 7 ]; then
echo "Wrong call to create_dev!"
exit 1
fi

NAME=$1
MAJ=$2
MIN=$3
TYP=$4
COUNT=$5
MODE=$6
OWNER=$7

if [ $COUNT != 1 ]; then
echo "create_dev called with count=$COUNT"
exit 1
fi
echo "Creating $DEV/$NAME: Major=$MAJ Minor=$MIN Mode=$MODE Owner=$OWNER"
if [ $RPM -eq 0 ]; then
rm -f $DEV/$NAME
mknod -m $MODE $DEV/$NAME $TYP $MAJ $MIN
chown $OWNER $DEV/$NAME
else
GROUP=${OWNER#*:}
USER=${OWNER%:*}
echo"%attr($MODE,$USER,$GROUP) %dev($TYP,$MAJ,$MIN) /$DEV/$NAME">> devfilelist
fi
}

#########################################################################
# Create a range of devices starting with 0.
#########################################################################

function create_dev_range () {
if [ $# != 7 ]; then
echo "Wrong call to create_dev_range!"
exit 1
fi

NAME=$1
MAJ=$2
MIN=$3
TYP=$4
COUNT=$5
MODE=$6
OWNER=$7

COUNTER=0
echo "Creating $DEV/$NAME$COUNTER to $DEV/$NAME`expr $COUNT - 1`: Major=$MAJ Mode=$MODE Owner=$OWNER"
while [ $COUNTER -lt $COUNT ] ; do
if [ $RPM -eq 0 ] ; then
rm -f $DEV/$NAME$COUNTER
mknod -m $MODE $DEV/$NAME$COUNTER $TYP $MAJ `expr $MIN + $COUNTER`
chown $OWNER $DEV/$NAME$COUNTER
else
GROUP=${OWNER#*:}
USER=${OWNER%:*}
echo"%attr($MODE,$USER,$GROUP) %dev($TYP,$MAJ,`expr $MIN + $COUNTER`) /$DEV/$NAME$COUNTER" >> devfilelist
fi

COUNTER=`expr $COUNTER + 1`
done
}

#########################################################################
# Create a range of devices starting with 1.
#########################################################################

function create_dev_range1 () {
if [ $# != 7 ]; then
echo "Wrong call to create_dev_range!"
exit 1
fi

NAME=$1
MAJ=$2
MIN=$3
TYP=$4
COUNT=$5
MODE=$6
OWNER=$7

COUNTER=1
echo "Creating $DEV/$NAME$COUNTER to $DEV/$NAME`expr $COUNT - 1`: Major=$MAJ Mode=$MODE Owner=$OWNER"
while [ $COUNTER -lt $COUNT ] ; do
if [ $RPM -eq 0 ] ; then
rm -f $DEV/$NAME$COUNTER
mknod -m $MODE $DEV/$NAME$COUNTER $TYP $MAJ `expr $MIN + $COUNTER`
chown $OWNER $DEV/$NAME$COUNTER
else
GROUP=${OWNER#*:}
USER=${OWNER%:*}
echo"%attr($MODE,$USER,$GROUP) %dev($TYP,$MAJ,`expr $MIN + $COUNTER`) /$DEV/$NAME$COUNTER" >> devfilelist
fi

COUNTER=`expr $COUNTER + 1`
done
}

#

#########################################################################

# Devices sda..sdz and sdaa..sdiv are part of the "devs" package, so we
# generated sdiw..sdzz (+partitions)
MAJOR=8
MINOR=256
MINOR_BASE=256
# Counters for the characters
# "i"
C1=8
# "w"
C2=22

# "increment" the (MAJOR,MINOR) pair for the next device. The device number to
# disk mapping is complex for historical reasons; see drivers/scsi/sd.c in the
# kernel source for details.
function step() {
if test x$(expr $MINOR % 256) == 'x0'; then
case $MAJOR in
8) MAJOR=65
;;
65 | 66 | 67 | 68 | 69 | 70)
MAJOR=$(expr $MAJOR + 1)
;;
71) MAJOR=128
;;
128 | 129 | 130 | 131 | 132 | 133 | 134)
MAJOR=$(expr $MAJOR + 1)
;;
135) MAJOR=8
MINOR_BASE=$(expr $MINOR_BASE + 256)
;;
*)
echo "Out of scope. Exiting"
exit 1
;;
esac
MINOR=$MINOR_BASE
fi
}

alphabet='abcdefghijklmnopqrstuvwxyz'
i=1;
while true; do
char1=${alphabet:$C1:1}
char2=${alphabet:$C2:1}

create_dev sd${char1}${char2} $MAJOR $MINOR b 1 660 root:disk
create_dev_range1 sd${char1}${char2} $MAJOR $MINOR b 16 660 root:disk

if test x${char1}${char2} = xzz; then
exit 0;
fi

C2=$(expr $C2 + 1)
if test $C2 == 26; then
C1=$(expr $C1 + 1);
C2=0;
fi

# Update/jump counters for major and minor device numbers
MINOR=$(expr $MINOR + 16)
step
done