<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
        <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
        <TITLE></TITLE>
        <META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.0  (Linux)">
        <META NAME="CREATED" CONTENT="20040215;13342400">
        <META NAME="CHANGED" CONTENT="20040216;13450400">
        <STYLE>
        <!--
                @page { size: 21.59cm 27.94cm }
        -->
        </STYLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<H1>The Linux multipath implementation</H1>
<P>Original author : Christophe Varoqui, Feb 2004</P>
<P>This document is shared under the OpenContent Licence
(<A HREF="http://www.opencontent.org/opl.shtml">http://www.opencontent.org/opl.shtml</A>)</P>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>Introduction</FONT></FONT></P>
<P>The most common multipathed environment today is a Fibre Channel
(FC) Storage Area Network (SAN). This beasts can be found in most
Datacenters. The lego blocks forming a SAN are :</P>
<UL>
        <LI><P>FC switchs : core switchs (multiprotocols chassis and FC
        boards), or stacked switchs linked by Inter Switch Links (ISL). This
        layer, the Fabric layer, can be subdived in two major fabric types :</P>
        <UL>
                <LI><P>Simple fabrics : all storage ports can be routed to all
                hosts ports. Hosts an storage controlers can have a single
                attachement to the the fabric.</P>
                <LI><P>Dual independent Fabrics : two sets of switchs are
                completely segregated (no ISL). They form two independent naming
                domains. The hosts and storage controlers must be attached the the
                two fabrics to assure redondancy. This technology is used to
                provide the maximum availability as one fabric can be shut, for
                planned or unplanned reasons, without pertubation seen on the other
                one.</P>
        </UL>
        <LI><P>FC storage controlers : most of them provide multiple ports
        to attach to the switchs layer. The physical storage they drive is
        arranged in virtual drives we will refer to as Logical Units (LU).
        Each LU is provided by its host controler a unique identifier as per
        the SCSI standard. We will refer to this identifier as the World
        Wide Identifier (WWID) or World Wide Name (WWN).</P>
        <LI><P>Host Bus Controlers (HBA) : the PCI / FC coupling adapters. A
        server can embed multiple HBA.</P>
</UL>
<P>The multipath term simply means that a host can acess a LU by
muliple paths, the path being a route from one host HBA port to one
storage controler port.</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-inside: avoid">
        <COL WIDTH=256*>
        <THEAD>
                <TR>
                        <TD WIDTH=100% VALIGN=TOP BGCOLOR="#cccccc">
                                <P>Examples :</P>
                                <UL>
                                        <LI><P>A host with 2 HBA attached to a single fabric is
                                        presented a LU by a 4 ports storage controler. The host then see
                                        8 paths to the LU</P>
                                        <LI><P>A host with 2 HBA attached to a dual independent fabric
                                        (1 HBA on eache fabric) is presented a LU by a 4 ports storage
                                        controler (2 ports on each fabric). The host then see 4 paths to
                                        the LU : 2 paths through fabric A, plus 2 through the fabric B.</P>
                                </UL>
                        </TD>
                </TR>
        </THEAD>
</TABLE>
<P><BR><BR>
</P>
<P>The Linux kernel choose not the mask the individual paths, that
appears as normal SCSI Disks (SD).</P>
<P>Multipath awareness and support for an operating system can be
described as :</P>
<UL>
        <LI><P>Provide a single block device node for a multipathed LU</P>
        <LI><P>Ensure that IO are re-routed to available paths when a loss
        of path occurs, with no userspace process disruption other than an
        short pause.</P>
        <LI><P>Ensure that failed paths get revalidated as soon as possible</P>
        <LI><P>Ensure stability of the naming of that node</P>
        <LI><P>Configure the multipaths to maximize performance : spread IO
        when possible path switching is free, and not spread when it's
        costly. 
        </P>
        <LI><P>Configure the multipaths automatically early at boot to
        permit OS install on a multipathed LU</P>
        <LI><P>Reconfigure the multipaths automatically when events occur</P>
        <LI><P>The multipath must be partitionable</P>
        <LI><P>In the Linux way : simple and hardware vendor agnostic</P>
</UL>
<P>All these goals are met by leveraging a set of userspace tools ans
kernel subsystems :</P>
<UL>
        <LI><P>the kernel device mapper</P>
        <LI><P>the hotplug kernel subsystem</P>
        <LI><P>the udev device naming tool</P>
        <LI><P>the multipath userspace configuration tool</P>
        <LI><P>the kpartx userspace configuration tool</P>
        <LI><P>the early userspace Linux kernel boot environment</P>
</UL>
<P>The rest of this document describes these individual tools and
subsystems and their interactions.</P>
<P><FONT FACE="Albany, sans-serif"><FONT SIZE=4>Device Mapper</FONT></FONT></P>
<P>Starting with Linux kernel 2.6, a new lightweight block subsystem
named Device Mapper enables advanced storage management with style.
This component features a plugable design. At the time of this
writing available plugins are :</P>
<UL>
        <LI><P>segments concatenation</P>
        <LI><P>segment striping</P>
        <LI><P>segment snapshoting</P>
        <LI><P>segment mirroring, with and without persistance</P>
        <LI><P>segment on-the-fly encryption</P>
        <LI><P>segment multipathing</P>
</UL>
<P>This last policy is the core component of the multipath tool
chain. It is not included in the main kernel tree as of linux-2.6.3.
It is part of a patchset maintained by Joe Thornber (thornber at
redhat dot com) that can be downloaded at
<A HREF="http://people.sistina.com/~thornber/dm/">http://people.sistina.com/~thornber/dm/</A></P>
<P>This component fills the following requirements :</P>
<UL>
        <LI><P>Provide a single block device node for a multipathed LU</P>
        <LI><P>Ensure that IO are re-routed to available paths when a loss
        of path occurs, with no userspace process disruption other than an
        short pause.</P>
        <LI><P>Ensure that failed paths get revalidated as soon as possible</P>
</UL>
<P>So, let's see how it works.</P>
<P>The Device Mapper is configured one map at a time. A device map,
also referred to as a table, is a list of segments in the form of :</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-inside: avoid">
        <COL WIDTH=256*>
        <THEAD>
                <TR>
                        <TD WIDTH=100% VALIGN=TOP BGCOLOR="#cccccc">
                                <P STYLE="margin-bottom: 0cm"><FONT FACE="Courier, monospace">0
                                35258368 linear 8:48 65920</FONT></P>
                                <P STYLE="margin-bottom: 0cm"><FONT FACE="Courier, monospace">35258368
                                35258368 linear 8:32 65920</FONT></P>
                                <P STYLE="margin-bottom: 0cm"><FONT FACE="Courier, monospace">70516736
                                17694720 linear 8:16 17694976</FONT></P>
                                <P><FONT FACE="Courier, monospace">88211456 17694720 linear 8:16
                                256</FONT></P>
                        </TD>
                </TR>
        </THEAD>
</TABLE>
<P><BR><BR>
</P>
<P>The first 2 parameters of each line are the segment starting block
in the virtual device and the lengh of the segment. The next keyword
ist the target policy (linear). The rest of the line is the target
parameters.</P>
<P>The Device Mapper can be fed its tables through the use of a
library : libdevmapper. Dmsetup, LVM2, the multipath configuration
tool and kpartx all link this lib. A table setup boils down to
sprintf'ing the right segment definitions in a char *. Should the DM
user-kernel interface change from being ioctl based to a pseudo
filesystem, the libdevmapper API should remain stable.</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-inside: avoid">
        <COL WIDTH=256*>
        <THEAD>
                <TR>
                        <TD WIDTH=100% VALIGN=TOP BGCOLOR="#cccccc">
                                <P>Here is an example of a multipath target :</P>
                                <P><FONT FACE="Courier, monospace">0 27262976 multipath 10 2 1
                                round-robin 2 0 /dev/sda /dev/sdk 1 round-robin 2 0 /dev/sdc
                                /dev/sdm</FONT></P>
                        </TD>
                </TR>
        </THEAD>
</TABLE>
<P><BR><BR>
</P>
<P>The multipath target parameters are :</P>
<UL>
        <LI><P>$0 : the “multipath” keyword</P>
        <LI><P>$1 : the test IO posting interval, used to revalidate failed
        paths, in seconds</P>
        <LI><P>$2 : the number of priority groups for the segment</P>
        <LI><P>$3 : the first priority group parameters :</P>
        <UL>
                <LI><P>$3.1 : the priority of this PG</P>
                <LI><P>$3.2 : the scheduler to be used to spread IO inside the PG</P>
                <LI><P>$3.3 : the number of paths in the PG</P>
                <LI><P>$3.4 : the number of paths parameters (usualy 0)</P>
                <LI><P>$3.5 : the paths list for this PG</P>
        </UL>
        <LI><P>$4 : next priority group</P>
</UL>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-inside: avoid">
        <COL WIDTH=256*>
        <THEAD>
                <TR>
                        <TD WIDTH=100% VALIGN=TOP BGCOLOR="#cccccc">
                                <P>For completion, here is an example of a pure failover target
                                definition for the same LU :</P>
                                <P><FONT FACE="Courier, monospace">0 27262976 multipath 10 4 1
                                round-robin 1 0 /dev/sda 1 round-robin 1 0 /dev/sdc 1 round-robin
                                1 0 /dev/sdk 1 round-robin 1 0 /dev/sdm</FONT></P>
                                <P><FONT FACE="Nimbus Roman No9 L">And a full spread (multibus)
                                target one :</FONT></P>
                                <P><FONT FACE="Courier, monospace">0 27262976 multipath 10 1 1
                                round-robin 4 0 /dev/sda /dev/sdc /dev/sdk /dev/sdm</FONT></P>
                        </TD>
                </TR>
        </THEAD>
</TABLE>
<P><BR><BR>
</P>
<P>Upon device map creating, a new block kernel object named
dm-[0-9]* is instantiated, and a hotplug call is triggered. Each
device map can be assigned a symbolic name when created through
libdevmapper, but this name won't be available anywhere but through a
libdevmapper request.</P>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>hotplug
subsystem and udev</FONT></FONT></P>
<P>Starting with Linux kernel 2.6, the hotplug callbacks are
commonized through the presence of a new pseudo filesystem : sysfs.
This filesystem presents to userspace kernel objects like bus, driver
instances or block devices in a hierarchicaly and homogenous manner.
The hotplug subsystem is leveraged by triggering a /sbin/hotplug call
upon file creation and deletion in the sysfs filesystem.</P>
<P>For our needs this facility provides :</P>
<UL>
        <LI><P>userspace callbacks upon paths additions and suppressions</P>
        <LI><P>userspace callbacks upon device maps additions and
        suppressions</P>
</UL>
<P>It may also provide in the future callbacks upon FC transport
events like a “Port Database Rescan”. This callbacks could then
be used to trigger SCSI Bus Rescan to bring a fully dynamic storage
layer.</P>
<P>Here is how we use this callbacks for the multipath implementation
:</P>
<UL>
        <LI><P>The paths additions and suppressions callbacks are routed to
        the multipath userspace configuration tool described later. This
        tool ensure the multipath maps are always up-to-date with the fabric
        topology, and this ensure optimal performance by adding new paths to
        the existing maps as soon as they become available.</P>
        <LI><P>The udev userspace tool is triggered upon every block sysfs
        entry creation and suppression, and assume the responsibility of the
        associated device node creation and naming. Udev default naming
        policies can be complemented by add-on scripts or binaries. As it
        does not currently have a default policy for device maps naming, we
        plug a little tool named devmap_name that resolve the sysfs
        dm-[0-9]* names in map names as set at map creation time. Provided
        the map naming is rightly done, this plugin provides the naming
        stability and meaningfullness required for a proper multipath
        implementation.</P>
        <LI><P>The userspace callbacks upon device maps additions and
        suppressions also triggers the kpartx tool to create the device maps
        over eventual partitions</P>
</UL>
<P>Udev is a reimplementation in userspace of the devfs kernel
facility. It provides a dynamic /dev space, with an agnostic naming
policy. Greg Kroah-Hartman is the main developer and maintainer of
this package. It can be found at
<A HREF="http://ftp.kernel.org/pub/linux/utils/kernel/hotplug/">http://ftp.kernel.org/pub/linux/utils/kernel/hotplug/</A></P>
<P>To synthetize what implementation details these subsystems fill :</P>
<UL>
        <LI><P>Ensure stability of the naming of that node</P>
        <LI><P>Reconfigure the multipaths automatically when events occur</P>
        <LI><P>The multipath must be partitionable</P>
</UL>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>multipath
userspace config tool</FONT></FONT></P>
<P>This tool is responsible for the paths coalescing and device maps
creation. As seen earlier, it is triggered by the hotplug calls on
new paths additions and suppressions. It must deal with hardware
specifics and abstract them for the others subsystems.</P>
<P>Here is how it works :</P>
<UL>
        <LI><P>draw a list of all available devices in the system through a
        sysfs scan. For each device, get a bunch of information :</P>
        <UL>
                <LI><P>Host / Bus / Target / Lun tuple</P>
                <LI><P>SCSI Device Strings : Vendor / Model / Revision</P>
                <LI><P>SCSI Serial String</P>
        </UL>
        <LI><P>Considering the informations fetched, elect a LU WWID method
        and an IO spreading policy. Ie deal with hardware specifics.</P>
        <LI><P>Get the LU WWID with the elected method. This method defaults
        to the standard 128 bit EUID found in the EVPD 0x83 inquiry page of
        the device.</P>
        <LI><P>Coalesce the paths to form the multipath structs</P>
        <LI><P>Create and name the device maps associated with the multipath
        structs with the selected IO spreading policy</P>
</UL>
<P>There are currently 3 spreading policy implemented :</P>
<UL>
        <LI><P>failover : 1 path per priority group. IO thus get routed to
        one path only.</P>
        <LI><P>multibus : 1 priority group containing all paths to the LU.
        Brings the maximum spreading, but assumes that all paths are
        sollicitable without penalty.</P>
        <LI><P>group_by_serial : 1 priority group per storage controler
        (serial), paths through one controler are assigned to the associated
        PG. This policy applies to controlers that impose a latency penalty
        on LU management hand-over between a pair of redondant controlers.</P>
</UL>
<P>The device maps naming policy is “name by LU WWID”.</P>
<TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3 STYLE="page-break-inside: avoid">
        <COL WIDTH=256*>
        <THEAD>
                <TR>
                        <TD WIDTH=100% VALIGN=TOP BGCOLOR="#cccccc">
                                <P>To illustrate this synopsis, here is an example verbose output
                                :</P>
                                <DL>
                                        <DD><FONT FACE="Courier, monospace">xa-s03:~/udev-016/extras#
                                        multipath -v</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156d700012000000b0000
                                        (0 0 1 1) /dev/sda [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156c30001200000210000
                                        (0 0 1 2) /dev/sdb [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156d700012000000b0000
                                        (0 0 2 1) /dev/sdc [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156c30001200000210000
                                        (0 0 2 2) /dev/sdd [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad0000903507109004b
                                        (0 0 3 1) /dev/sde [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100bf
                                        (0 0 3 2) /dev/sdf [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100c2
                                        (0 0 3 3) /dev/sdg [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad00009037131210067
                                        (0 0 4 1) /dev/sdh [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100b3
                                        (0 0 4 2) /dev/sdi [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad00009035071090024
                                        (0 0 4 3) /dev/sdj [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156d700012000000b0000
                                        (1 0 1 1) /dev/sdk [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156c30001200000210000
                                        (1 0 1 2) /dev/sdl [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156d700012000000b0000
                                        (1 0 2 1) /dev/sdm [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156c30001200000210000
                                        (1 0 2 2) /dev/sdn [HSV110 (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156d700012000000b0000</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 1 1) /dev/sda [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 2 1) /dev/sdc [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(1 0 1 1) /dev/sdk [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(1 0 2 1) /dev/sdm [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">600508b4000156c30001200000210000</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 1 2) /dev/sdb [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 2 2) /dev/sdd [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(1 0 1 2) /dev/sdl [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(1 0 2 2) /dev/sdn [HSV110
                                        (C)COMPAQ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad0000903507109004b</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 3 1) /dev/sde [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100bf</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 3 2) /dev/sdf [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100c2</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 3 3) /dev/sdg [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad00009037131210067</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 4 1) /dev/sdh [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad000090371312100b3</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 4 2) /dev/sdi [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">60001fe1000bdad00009035071090024</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">\_(0 0 4 3) /dev/sdj [HSG80 ]</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:600508b4000156d700012000000b0000:0
                                        27262976 multipath 10 2 1 round-robin 2 0 /dev/sda /dev/sdk 1
                                        round-robin 2 0 /dev/sdc /dev/sdm</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:600508b4000156c30001200000210000:0
                                        31457280 multipath 10 2 1 round-robin 2 0 /dev/sdb /dev/sdl 1
                                        round-robin 2 0 /dev/sdd /dev/sdn</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad0000903507109004b:0
                                        106669167 multipath 10 1 1 round-robin 1 0 /dev/sde</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad000090371312100bf:0
                                        142229246 multipath 10 1 1 round-robin 1 0 /dev/sdf</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad000090371312100c2:0
                                        142229246 multipath 10 1 1 round-robin 1 0 /dev/sdg</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad00009037131210067:0
                                        213338334 multipath 10 1 1 round-robin 1 0 /dev/sdh</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad000090371312100b3:0
                                        213338334 multipath 10 1 1 round-robin 1 0 /dev/sdi</FONT></DD><DD>
                                        <FONT FACE="Courier, monospace">U:60001fe1000bdad00009035071090024:0
                                        71114623 multipath 10 1 1 round-robin 1 0 /dev/sdj</FONT></DD></DL>
                        </TD>
                </TR>
        </THEAD>
</TABLE>
<P><BR><BR>
</P>
<P>The first section shows the list of all paths detected on the
host. The second shows the multipath structs produced by the
coalescing logic. The third shows the device maps submited to the
Device Mapper.</P>
<P>Of interest is the creation of device maps for single path LU :
this enable to system to operate normaly when booted in a degraded
SAN context. The missing paths will be added to the maps when they
become available.</P>
<P>This tool is packaged with udev, in the extras/ section. The
devmap_name tool is distributed in the same tree.</P>
<P>The implementation requirements filled by this tool are :</P>
<UL>
        <LI><P>Ensure stability of the naming of that node (in complement of
        udev)</P>
        <LI><P>Configure the multipaths to maximize performance : spread IO
        when possible path switching is free, and not spread when it's
        costly. 
        </P>
        <LI><P>Configure the multipaths automatically at boot</P>
        <LI><P>Reconfigure the multipaths automatically when events occur (
        in complement of hotplug)</P>
</UL>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>kpartx
userspace config tool</FONT></FONT></P>
<P>This tool, derived from util-linux' partx, reads partition tables
on specified device and create device maps over partitions segments
detected. It is called from hotplug upon device maps creation and
deletion.</P>
<P>For now kpartx can be found at <A HREF="http://dsit.free.fr/">http://dsit.free.fr/</A></P>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>Early
userspace</FONT></FONT></P>
<P>Starting with Linux kernel 2.6, an early userspace execution
environment is available in the name of initramfs. The grand plan is
to package a set of tools in a cpio archive concatanated to the
kernel. This archive is expanded in an in-memory filesystem early at
boot and the tools are called to assume logics that previously
belonged in the kernel : dhcp requests and setups, nfsroot stuffing
...</P>
<P>Being concatenated to the kernel, the size of this archive matters
a lot. A slim libc implementation is required and provided in the
name of klibc, maintained by Hans Peter Anvin.</P>
<P>The multipath implementation toolchain fits in this early
userspace definition. Udev, multipath and kpartx are linked against
klibc and can be packaged with the cpio archive to bring up the
multipathed device early enough to boot on.</P>
<P>So is met the last multipath implementation requirement.</P>
<P STYLE="margin-top: 0.42cm; page-break-after: avoid"><FONT FACE="Albany, sans-serif"><FONT SIZE=4>Quick
installation guide</FONT></FONT></P>
<UL>
        <LI><P>Download and unarchive a recent 2.6 kernel</P>
        <LI><P>Download, unarchive and apply the associated udm patchset
        from <A HREF="http://people.sistina.com/~thornber/dm/">http://people.sistina.com/~thornber/dm/</A></P>
        <LI><P>Configure, compile and install the kernel, reconfigure the
        bootloader if needed</P>
        <LI><P>Download udev, at least 017, from
        <A HREF="http://ftp.kernel.org/pub/linux/utils/kernel/hotplug/">http://ftp.kernel.org/pub/linux/utils/kernel/hotplug/</A></P>
        <LI><P>Compile udev with klibc linking (edit the Makefile to
        uncomment KLIBC=true). Make install.</P>
        <LI><P>In udev/extras/multipath, make and make install</P>
        <LI><P>Reboot under the new kernel and see the magic operate</P>
</UL>
</BODY>
</HTML>