diff --git a/kpartx/Makefile b/kpartx/Makefile
index d970d29..e6a7296 100644
--- a/kpartx/Makefile
+++ b/kpartx/Makefile
@@ -37,8 +37,10 @@ $(MULTIPATHLIB)-$(BUILD).a:
 install: $(EXEC) kpartx_id $(EXEC).8
 	install -d $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+	install -m 755 activate_dm_linear $(DESTDIR)$(bindir)
 	install -d $(DESTDIR)$(libudevdir)
 	install -m 755 kpartx_id $(DESTDIR)$(libudevdir)
+	install -m 755 dm_linear $(DESTDIR)$(libudevdir)
 	install -d $(DESTDIR)/etc/udev/rules.d
 	install -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules
 	install -d $(DESTDIR)$(mandir)
@@ -46,6 +48,11 @@ install: $(EXEC) kpartx_id $(EXEC).8
 
 uninstall:
 	rm -f $(DESTDIR)$(bindir)/$(EXEC)
+	rm -f $(DESTDIR)$(bindir)/activate_dm_linear
+	rm -f $(DESTDIR)$(libudevdir)/kpartx_id
+	rm -f $(DESTDIR)$(libudevdir)/dm_linear
+	rm -f $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules
+	rm -f $(DESTDIR)$(mandir)/$(EXEC).8
 
 clean:
 	rm -f core *.o $(EXEC)
diff --git a/kpartx/activate_dm_linear b/kpartx/activate_dm_linear
new file mode 100644
index 0000000..7481bd4
--- /dev/null
+++ b/kpartx/activate_dm_linear
@@ -0,0 +1,76 @@
+#!/bin/sh
+#
+# activate_dm_linear
+#
+# Activate a linear mapping on top of an existing block device.
+# This allows for partitions to be mapped via kpartx, so all
+# partitions on a device can be accessed.
+#
+
+RULE=/etc/udev/rules.d/62-dm_linear.rules
+
+if [ -z "$1" ] ; then
+    echo "Usage: $0 [-d] devname"
+    exit 1
+fi
+
+if [ "$1" == "-d" ] ; then
+    remove_only=1
+    shift
+fi
+
+if [ ! -b "$1" ] ; then
+    echo "$1 is not a block device"
+    exit 1
+fi
+
+dev=${1#/dev/}
+
+if [ ! -d /sys/block/$dev ] ; then
+    echo "$1 is not a disk device"
+    exit 1
+fi
+
+blksize=$(/sbin/blockdev --getsize $1)
+if [ $? -ne 0 ] ; then
+    echo "blockdev --getsize $1 failed: $?"
+    exit 1
+fi
+
+for link in $(udevinfo -q symlink -p /block/$dev) ; do
+    case "$link" in
+	*/by-id/ata*)
+            atalink=${link#*/by-id/ata-}
+	    ;;
+	*/by-id/scsi*)
+	    scsilink=${link#*/by-id/scsi-}
+	    ;;
+    esac
+done
+if [ "$atalink" ] ; then
+    serial="$atalink"
+    bus="ata"
+fi
+if [ "$scsilink" ] ; then
+    unset atalink
+    serial="$scsilink"
+    bus="scsi"
+fi
+if [ "$serial" ]; then
+    # Remove existing rules
+    echo "/$serial/d
+w
+q
+" | ed $RULE > /dev/null 2>&1
+    [ "$remove_only" = 1 ] && exit 0
+    # And create a new one
+    if [ "$atalink" ] ; then
+	cat >> $RULE <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_VENDOR}=="ATA", ENV{ID_ATA_COMPAT}=="$serial", RUN+="dm_linear /dev/\$kernel $blksize ata-\$env{ID_ATA_COMPAT}"
+EOF
+    else
+	cat >> $RULE <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="$bus", ENV{ID_SERIAL}=="$serial", RUN+="dm_linear \$kernel /dev/$blksize \$env{ID_BUS}-\$env{ID_SERIAL}"
+EOF
+    fi
+fi
diff --git a/kpartx/dm_linear b/kpartx/dm_linear
new file mode 100755
index 0000000..d1de7e4
--- /dev/null
+++ b/kpartx/dm_linear
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Create a linear table on top of a given device
+# usage:
+#         dm_linear <dev> <size> <name>
+#
+
+if [ -z "$1" ] ; then
+    exit 1
+fi
+
+if [ ! -b "$1" ] ; then
+    exit 2
+fi
+
+if [ -z "$2" ] ; then
+    exit 3
+fi
+
+if [ -z "$3" ] ; then
+    exit 4
+fi
+
+echo 0 $2 linear $1 0 | /sbin/dmsetup create "$3" -u "linear-$3"
+
+exit $?
+
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 9ab9a49..2746eff 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -21,6 +21,10 @@ ENV{DM_UUID}=="mpath-*", \
 ENV{DM_UUID}=="dmraid-*", \
         SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
 
+# Create persistent links for linear tables
+ENV{DM_UUID}=="linear-*", \
+        SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
+
 # Create persistent links for partitions
 ENV{DM_PART}=="?*", \
         SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}-part$env{DM_PART}"
@@ -30,6 +34,8 @@ ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \
         RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
 ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="dmraid-*", \
         RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
+ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="linear-*", \
+        RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
 
 LABEL="kpartx_end"
 
diff --git a/kpartx/kpartx_id b/kpartx/kpartx_id
index 81f32bf..c402e98 100644
--- a/kpartx/kpartx_id
+++ b/kpartx/kpartx_id
@@ -50,7 +50,7 @@ else
 fi
 
 # Set the name of the table. We're only interested in dmraid,
-# multipath, and kpartx tables; everything else is ignored.
+# multipath, linear, and kpartx tables; everything else is ignored.
 if [ "$dmtbl" = "part" ] ; then
     # The name of the kpartx table is the name of the parent table
     dmname=$($DMSETUP info  -c --noheadings -o name -u $dmuuid)
@@ -61,6 +61,10 @@ if [ "$dmtbl" = "part" ] ; then
 	mpath-*)
 	    dmdeps=$($DMSETUP deps -u $dmuuid)
 	    ;;
+	linear-*)
+	    dmtbl=linear
+	    dmuuid=${dmuuid#*-}
+	    ;;
     esac
 elif [ "$dmtbl" = "mpath" ] ; then
     dmname=$tblname
@@ -72,8 +76,8 @@ fi
 
 [ -n "$dmpart" ] && echo "DM_PART=$dmpart"
 
-# Figure out the type of the map. For non-multipath maps it's
-# always 'raid'.
+# Figure out the type of the map. For non-multipath non-linear 
+# maps it's always 'raid'.
 if [ -n "$dmdeps" ] ; then
     case "$dmdeps" in
 	*\(94,*)
@@ -86,6 +90,9 @@ if [ -n "$dmdeps" ] ; then
             echo "DM_TYPE=scsi"
 	    ;;
     esac
+elif [ "$dmtbl" = linear ]; then
+    echo "DM_TYPE=${dmuuid%%-*}"
+    echo "DM_NAME=${dmuuid#*-}"
 else
     echo "DM_TYPE=raid"
 fi
