[dm-devel] dmraid ./CHANGELOG ./KNOWN_BUGS ./README ./dmr ...

heinzm at sourceware.org heinzm at sourceware.org
Wed Apr 2 13:35:36 UTC 2008


CVSROOT:	/cvs/dm
Module name:	dmraid
Changes by:	heinzm at sourceware.org	2008-04-02 13:35:32

Modified files:
	.              : CHANGELOG KNOWN_BUGS README dmraid.spec 
	include/dmraid : lib_context.h 
	lib            : internal.h version.h 
	lib/activate   : activate.c devmapper.c 
	lib/format     : format.c 
	lib/format/ataraid: asr.c isw.c jm.c lsi.c lsi.h nv.c pdc.c 
	                    pdc.h 
	lib/format/ddf : ddf1.c ddf1_crc.c 
	lib/format/partition: dos.c 
	lib/metadata   : metadata.c 
	lib/misc       : lib_context.c 
	man            : dmraid.8 
	tools          : VERSION commands.c commands.h 

Log message:
	1.0.0.rc15-pre checkin

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/CHANGELOG.diff?cvsroot=dm&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/KNOWN_BUGS.diff?cvsroot=dm&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/README.diff?cvsroot=dm&r1=1.5&r2=1.6
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/dmraid.spec.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/include/dmraid/lib_context.h.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/internal.h.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/version.h.diff?cvsroot=dm&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/activate/activate.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/activate/devmapper.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/format.c.diff?cvsroot=dm&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/asr.c.diff?cvsroot=dm&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/isw.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/jm.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/lsi.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/lsi.h.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/nv.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/pdc.c.diff?cvsroot=dm&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ataraid/pdc.h.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/ddf/ddf1_crc.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/format/partition/dos.c.diff?cvsroot=dm&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/metadata/metadata.c.diff?cvsroot=dm&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/lib/misc/lib_context.c.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/man/dmraid.8.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/VERSION.diff?cvsroot=dm&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/commands.c.diff?cvsroot=dm&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/dmraid/tools/commands.h.diff?cvsroot=dm&r1=1.1&r2=1.2

--- dmraid/CHANGELOG	2008/02/22 17:06:54	1.4
+++ dmraid/CHANGELOG	2008/04/02 13:35:30	1.5
@@ -1,4 +1,21 @@
 
+Changelog from dmraid 1.0.0.rc14 to 1.0.0.rc15		2007.08.22
+
+FIXES:
+------
+o jm.c: fixed name handling, when whitespace added to end of name
+o nv.c: fixed endian bug (Bryn Reeves)
+
+
+FEATURES:
+---------
+
+
+MISCELANIOUS:
+-------------
+
+
+
 Changelog from dmraid 1.0.0.rc13 to 1.0.0.rc14		2006.11.08
 
 FIXES:
--- dmraid/KNOWN_BUGS	2008/02/22 17:06:54	1.3
+++ dmraid/KNOWN_BUGS	2008/04/02 13:35:30	1.4
@@ -1,4 +1,4 @@
 
-KNOWN_BUGS in dmraid 1.0.0.rc14					2005.11.08
+KNOWN_BUGS in dmraid 1.0.0.rc15					2008.04.02
 
 o "dmraid --sets[a/i]" doesn't work properly. Use the short option -s.
--- dmraid/README	2008/02/22 17:06:54	1.5
+++ dmraid/README	2008/04/02 13:35:30	1.6
@@ -1,8 +1,8 @@
 ********************************************************************************
 *                                                                              *
-*   dmraid (Device-Mapper Software RAID support tool) 1.0.0.rc14  2006.11.08   *
+*   dmraid (Device-Mapper Software RAID tool) 1.0.0.rc15-pre 2008.04.02        *
 *                                                                              *
-*   (C)opyright 2004-2006  Heinz Mauelshagen, Red Hat GmbH.                    *
+*   (C)opyright 2004-2008  Heinz Mauelshagen, Red Hat GmbH.                    *
 *   All rights reserved.                                                       *
 *                                                                              *
 ********************************************************************************
@@ -66,13 +66,13 @@
 --------------
 To install the rpm
 
-rpm -i [--nodeps] dmraid-1.0.0.rc10.i386.rpm
+rpm -i [--nodeps] dmraid-1.0.0.rc15.i386.rpm
 
 - or -
 
 to build in an empty directory and install from source
 
-tar jxvf dmraid-1.0.0.rc10.tar.bz2
+tar jxvf dmraid-1.0.0.rc15.tar.bz2
 ./configure	# see ./configure --help for options
 make
 make install
--- dmraid/dmraid.spec	2008/02/22 16:50:38	1.1
+++ dmraid/dmraid.spec	2008/04/02 13:35:30	1.2
@@ -6,7 +6,7 @@
 
 Summary: dmraid (Device-mapper RAID tool and library)
 Name: dmraid
-Version: 1.0.0.rc11
+Version: 1.0.0.rc15-pre
 Release: 1
 License: GPL
 Group: System Environment/Base
--- dmraid/include/dmraid/lib_context.h	2008/02/22 16:57:35	1.1
+++ dmraid/include/dmraid/lib_context.h	2008/04/02 13:35:31	1.2
@@ -38,7 +38,8 @@
 	LC_VERBOSE,
 	LC_IGNORELOCKING,
 	LC_SEPARATOR,
-	LC_DEVICES,	  /* Add new options below this one ! */
+	LC_DEVICES,
+	LC_PARTCHAR,	  /* Add new options below this one ! */
 	LC_OPTIONS_SIZE,  /* Must be the last enumerator. */
 };
 
@@ -55,12 +56,14 @@
 #define	OPT_SETS(lc)		(lc_opt(lc, LC_SETS))
 #define	OPT_TEST(lc)		(lc_opt(lc, LC_TEST))
 #define	OPT_VERBOSE(lc)		(lc_opt(lc, LC_VERBOSE))
+#define	OPT_PARTCHAR(lc)	(lc_opt(lc, LC_PARTCHAR))
 
 /* Return option value. */
 #define	OPT_STR(lc, o)		(lc->options[o].arg.str)
 #define	OPT_STR_COLUMN(lc)	OPT_STR(lc, LC_COLUMN)
 #define	OPT_STR_FORMAT(lc)	OPT_STR(lc, LC_FORMAT)
 #define	OPT_STR_SEPARATOR(lc)	OPT_STR(lc, LC_SEPARATOR)
+#define	OPT_STR_PARTCHAR(lc)	OPT_STR(lc, LC_PARTCHAR)
 
 struct lib_version {
 	const char *text;
--- dmraid/lib/internal.h	2008/02/22 17:04:35	1.2
+++ dmraid/lib/internal.h	2008/04/02 13:35:31	1.3
@@ -49,8 +49,8 @@
 #define	u_int64_t	uint64_t
 #endif
 
-#define min(a, b) a < b ? a : b
-#define max(a, b) a > b ? a : b
+#define min(a, b) (a) < (b) ? (a) : (b)
+#define max(a, b) (a) > (b) ? (a) : (b)
 #define ARRAY_SIZE(a)   (sizeof(a) / sizeof(*a))
 #define ARRAY_END(a)   (a + ARRAY_SIZE(a))
 
--- dmraid/lib/version.h	2008/02/22 17:06:54	1.4
+++ dmraid/lib/version.h	2008/04/02 13:35:31	1.5
@@ -1,12 +1,12 @@
 #ifndef	DMRAID_LIB_VERSION
 
-#define	DMRAID_LIB_VERSION		"1.0.0.rc14"
+#define	DMRAID_LIB_VERSION		"1.0.0.rc15"
 
 #define	DMRAID_LIB_MAJOR_VERSION	1
 #define	DMRAID_LIB_MINOR_VERSION	0
 #define	DMRAID_LIB_SUBMINOR_VERSION	0
-#define	DMRAID_LIB_VERSION_SUFFIX	"rc14"
+#define	DMRAID_LIB_VERSION_SUFFIX	"rc15"
 
-#define	DMRAID_LIB_DATE			"(2006.11.08)"
+#define	DMRAID_LIB_DATE			"(2008.04.02)"
 
 #endif
--- dmraid/lib/activate/activate.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/activate/activate.c	2008/04/02 13:35:31	1.3
@@ -398,7 +398,11 @@
 			goto err;
 	}
 
-	return 1;
+	/* Append the flag/feature required for dmraid1 
+	 * event handling in the kernel driver 
+	 */
+	if(p_fmt(lc, table, " 1 handle_errors"))
+		return 1;
 
    err:
 	return log_alloc_err(lc, __func__);
--- dmraid/lib/activate/devmapper.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/activate/devmapper.c	2008/04/02 13:35:31	1.3
@@ -21,6 +21,8 @@
 #include "internal.h"
 #include "devmapper.h"
 
+#include <linux/dm-ioctl.h>
+
 /* Make up a dm path. */
 char *mkdm_path(struct lib_context *lc, const char *name)
 {
@@ -147,24 +149,48 @@
 	return handle_table(lc, NULL, table, get_target_list());
 }
 
+/* Build a UUID for a dmraid device 
+ * Return 1 for sucess; 0 for failure*/
+static int dmraid_uuid(struct lib_context *lc, struct raid_set *rs,
+		       char *uuid, uint uuid_len) {
+	int r;
+
+	/* Clear garbage data from uuid string */
+	memset(uuid, 0, uuid_len);
+
+	/* Create UUID string from subsystem prefix and RAID set name. */
+	r = snprintf(uuid, uuid_len, "DMRAID-%s", rs->name) < uuid_len;
+	return r < 0 ? 0 : (r < uuid_len);
+}
+
 /* Create a task, set its name and run it. */
 static int run_task(struct lib_context *lc, struct raid_set *rs,
 		    char *table, int type)
 {
+	/* DM_UUID_LEN is defined in dm-ioctl.h as 129 characters;
+	 * though not all 129 must be used (md uses just 16 from 
+	 * a quick review of md.c. 
+	 * We will be using: (len vol grp name)*/ 
+	char uuid[DM_UUID_LEN];
 	int ret;
 	struct dm_task *dmt;
 
 	_init_dm();
-	ret = (dmt = dm_task_create(type)) && dm_task_set_name(dmt, rs->name);
+	ret = (dmt = dm_task_create(type)) &&
+	      dm_task_set_name(dmt, rs->name);
 	if (ret && table)
 		ret = parse_table(lc, dmt, table);
 
-	if (ret)
-		ret = dm_task_run(dmt);
+	if (ret && 
+	    DM_DEVICE_CREATE == type)
+		ret = dmraid_uuid(lc, rs, uuid, DM_UUID_LEN) &&
+		      dm_task_set_uuid(dmt, uuid) &&
+		      dm_task_run(dmt);
 
 	_exit_dm(dmt);
 	return ret;
 }
+	
 /* Create a mapped device. */
 int dm_create(struct lib_context *lc, struct raid_set *rs, char *table)
 {
--- dmraid/lib/format/format.c	2008/02/22 17:06:54	1.3
+++ dmraid/lib/format/format.c	2008/04/02 13:35:31	1.4
@@ -18,7 +18,7 @@
  * Comment next line out to avoid pre-registration
  * checks on metadata format handlers.
  */
-// #define	CHECK_FORMAT_HANDLER
+#define	CHECK_FORMAT_HANDLER
 #ifdef	CHECK_FORMAT_HANDLER
 /*
  * Check that mandatory members of a metadata form handler are present.
@@ -34,25 +34,25 @@
 #define offset(member)	struct_offset(dmraid_format, member)
 
 struct format_member {
-	const unsigned short offset;
-	const unsigned char flags;
 	const char *msg;
+	const unsigned short offset;
+	const unsigned short flags;
 } __attribute__ ((packed));
 
 enum { FMT_ALL = 0x01, FMT_METHOD = 0x02 } format_flags;
 #define	IS_FMT_ALL(member)	(member->flags & FMT_ALL)
 #define	IS_FMT_METHOD(member)	(member->flags & FMT_METHOD)
 static struct format_member format_member[] = {
-	{ offset(name), FMT_ALL, "name" },
-	{ offset(descr), FMT_ALL, "description" },
-	{ offset(caps), 0, "capabilities" },
-	{ offset(read), FMT_ALL|FMT_METHOD, "read" },
-	{ offset(write), FMT_METHOD, "write" },
-	{ offset(group), FMT_ALL|FMT_METHOD, "group" },
-	{ offset(check), FMT_ALL|FMT_METHOD, "check" },
-	{ offset(events), 0, "events array" },
+	{ "name", offset(name), FMT_ALL },
+	{ "description", offset(descr), FMT_ALL },
+	{ "capabilities", offset(caps), 0 },
+	{ "read", offset(read), FMT_ALL|FMT_METHOD },
+	{ "write", offset(write), FMT_METHOD },
+	{ "group", offset(group), FMT_ALL|FMT_METHOD },
+	{ "check", offset(check), FMT_ALL|FMT_METHOD },
+	{ "events array", offset(events), 0 },
 #ifdef	NATIVE_LOG
-	{ offset(log),    FMT_METHOD, "log" },
+	{ "log", offset(log), FMT_METHOD },
 #endif
 };
 #undef	offset
--- dmraid/lib/format/ataraid/asr.c	2008/02/22 17:06:00	1.3
+++ dmraid/lib/format/ataraid/asr.c	2008/04/02 13:35:31	1.4
@@ -49,11 +49,12 @@
 /* Extract config line from metadata */
 static struct asr_raid_configline *get_config(struct asr *asr, uint32_t magic)
 {
-	unsigned int i = asr->rt->elmcnt;
+	struct asr_raidtable *rt = asr->rt;
+	struct asr_raid_configline *cl = rt->ent + rt->elmcnt;
 	
-	while (i--) {
-		if (asr->rt->ent[i].raidmagic == magic)
-			return asr->rt->ent + i;
+	while (cl-- > rt->ent) {
+		if (cl->raidmagic == magic)
+			return cl;
 	}
 
 	return NULL;
@@ -92,7 +93,7 @@
 }
 
 /* Stride size */
-static inline unsigned int stride(struct asr_raid_configline *cl)
+static inline unsigned stride(struct asr_raid_configline *cl)
 {
 	return cl ? cl->strpsize: 0;
 }
@@ -114,8 +115,7 @@
 		{ 0, t_undef},
 	};
 
-printf("cl->raidtype=%d rd_type=%d\n", cl->raidtype, rd_type(types, (unsigned int) cl->raidtype));
-	return cl ? rd_type(types, (unsigned int) cl->raidtype) : t_undef;
+	return cl ? rd_type(types, (unsigned) cl->raidtype) : t_undef;
 }
 
 /*
@@ -141,11 +141,12 @@
 	CVT32(cl->appBurstCount);
 }
 
-static void to_cpu(void *meta, unsigned int cvt)
+static void to_cpu(void *meta, unsigned cvt)
 {
 	struct asr *asr = meta;
-	unsigned int i, elmcnt = asr->rt->elmcnt,
-		     use_old_elmcnt = (asr->rt->ridcode == RVALID2);
+	struct asr_raidtable *rt = asr->rt;
+	unsigned i, elmcnt = rt->elmcnt,
+		     use_old_elmcnt = (rt->ridcode == RVALID2);
 
 	if (cvt & ASR_BLOCK) {
 		CVT32(asr->rb.b0idcode);
@@ -161,29 +162,30 @@
 	}
 
 	if (cvt & ASR_TABLE) {
-		CVT32(asr->rt->ridcode);
-		CVT32(asr->rt->rversion);
-		CVT16(asr->rt->maxelm);
-		CVT16(asr->rt->elmcnt);
+		CVT32(rt->ridcode);
+		CVT32(rt->rversion);
+		CVT16(rt->maxelm);
+		CVT16(rt->elmcnt);
 		if (!use_old_elmcnt)
-			elmcnt = asr->rt->elmcnt;
-		CVT16(asr->rt->elmsize);
-		CVT32(asr->rt->raidFlags);
-		CVT32(asr->rt->timestamp);
-		CVT16(asr->rt->rchksum);
-		CVT32(asr->rt->sparedrivemagic);
-		CVT32(asr->rt->raidmagic);
-		CVT32(asr->rt->verifyDate);
-		CVT32(asr->rt->recreateDate);
+			elmcnt = rt->elmcnt;
+
+		CVT16(rt->elmsize);
+		CVT32(rt->raidFlags);
+		CVT32(rt->timestamp);
+		CVT16(rt->rchksum);
+		CVT32(rt->sparedrivemagic);
+		CVT32(rt->raidmagic);
+		CVT32(rt->verifyDate);
+		CVT32(rt->recreateDate);
 
 		/* Convert the first seven config lines */
 		for (i = 0; i < (min(elmcnt, ASR_TBLELMCNT)); i++) 
-			cvt_configline(asr->rt->ent + i);
+			cvt_configline(rt->ent + i);
 	}
 
 	if (cvt & ASR_EXTTABLE) {
 		for (i = ASR_TBLELMCNT; i < elmcnt; i++)
-			cvt_configline(asr->rt->ent + i);
+			cvt_configline(rt->ent + i);
 	}
 }
 
@@ -192,11 +194,11 @@
 #endif
 
 /* Compute the checksum of RAID metadata */
-static unsigned int compute_checksum(struct asr *asr)
+static unsigned compute_checksum(struct asr *asr)
 {
-	uint8_t *ptr = (uint8_t*) asr->rt->ent;
-	unsigned int checksum = 0,
-		     end = sizeof(*asr->rt->ent) * asr->rt->elmcnt;
+	struct asr_raidtable *rt = asr->rt;
+	uint8_t *ptr = (uint8_t*) rt->ent;
+	unsigned checksum = 0, end = sizeof(*rt->ent) * rt->elmcnt;
 
 	/* Compute checksum. */
 	while (end--)
@@ -209,7 +211,7 @@
 enum truncate { TRUNCATE, UNTRUNCATE };
 static void handle_white_space(uint8_t *p, enum truncate truncate)
 {
-	unsigned int j = ASR_NAMELEN;
+	unsigned j = ASR_NAMELEN;
 	uint8_t c = truncate == TRUNCATE ? 0 : ' ';
 
 	while (j-- && (truncate == TRUNCATE ? isspace(p[j]) : !p[j]))
@@ -220,12 +222,13 @@
 static int read_extended(struct lib_context *lc, struct dev_info *di,
 			 struct asr *asr)
 {
-	unsigned int remaining, i, chk;
+	unsigned remaining, i, chk;
+	struct asr_raidtable *rt = asr->rt;
 
 	log_notice(lc, "%s: reading extended data on %s", handler, di->path);
 	
 	/* Read the RAID table. */
-	if (!read_file(lc, handler, di->path, asr->rt, ASR_DISK_BLOCK_SIZE,
+	if (!read_file(lc, handler, di->path, rt, ASR_DISK_BLOCK_SIZE,
 		       (uint64_t) asr->rb.raidtbl * ASR_DISK_BLOCK_SIZE))
 		LOG_ERR(lc, 0, "%s: Could not read metadata off %s",
 			handler, di->path);
@@ -234,25 +237,25 @@
 	to_cpu(asr, ASR_TABLE);
 	
 	/* Is this ok? */
-	if (asr->rt->ridcode != RVALID2)
+	if (rt->ridcode != RVALID2)
 		LOG_ERR(lc, 0, "%s: Invalid magic number in RAID table; "
 			"saw 0x%X, expected 0x%X on %s",
-			handler, asr->rt->ridcode, RVALID2, di->path);
+			handler, rt->ridcode, RVALID2, di->path);
 
 	/* Have we a valid element count? */
-	if (asr->rt->elmcnt >= asr->rt->maxelm || asr->rt->elmcnt == 0)
+	if (rt->elmcnt >= rt->maxelm || rt->elmcnt == 0)
 		LOG_ERR(lc, 0, "%s: Invalid RAID config table count on %s",
 			handler, di->path);
 
 	/* Is each element the right size? */
-	if (asr->rt->elmsize != sizeof(*asr->rt->ent))
+	if (rt->elmsize != sizeof(*rt->ent))
 		LOG_ERR(lc, 0, "%s: Wrong RAID config line size on %s",
 			handler, di->path);
 
 	/* Figure out how much else we need to read. */
-	if (asr->rt->elmcnt > ASR_TBLELMCNT) {
-		remaining = asr->rt->elmsize * (asr->rt->elmcnt - 7);
-		if (!read_file(lc, handler, di->path, asr->rt->ent + 7,
+	if (rt->elmcnt > ASR_TBLELMCNT) {
+		remaining = rt->elmsize * (rt->elmcnt - 7);
+		if (!read_file(lc, handler, di->path, rt->ent + 7,
 			       remaining, (uint64_t)(asr->rb.raidtbl + 1) *
 			       ASR_DISK_BLOCK_SIZE))
 			return 0;
@@ -260,14 +263,16 @@
 		to_cpu(asr, ASR_EXTTABLE);
 	}
 
-	chk = compute_checksum(asr);
-	if (chk != asr->rt->rchksum)
-		LOG_ERR(lc, 0,"%s: Invalid RAID config table checksum "
-			       "(0x%X vs. 0x%X) on %s",
-			handler, chk, asr->rt->rchksum, di->path);
+	/* Checksum only valid for raid table version 1. */
+	if (rt->rversion < 2) {
+		if ((chk = compute_checksum(asr)) != rt->rchksum)
+			log_err(lc, "%s: Invalid RAID config table checksum "
+				       "(0x%X vs. 0x%X) on %s",
+				handler, chk, rt->rchksum, di->path);
+	}
 	
 	/* Process the name of each line of the config line. */
-	for (i = 0; i < asr->rt->elmcnt; i++) {
+	for (i = 0; i < rt->elmcnt; i++) {
 		/* 
 		 * Weird quirks of the name field of the config line:
 		 *
@@ -290,11 +295,13 @@
 		 *
 		 * This is nuts.
 		 */
-		if (!asr->rt->ent[i].name)
-			memcpy(asr->rt->ent[i].name, asr->rt->ent[0].name, 16);
+		if (!*rt->ent[i].name)
+			strncpy((char*) rt->ent[i].name,
+				(char*) rt->ent->name,
+				ASR_NAMELEN);
 
 		/* Now truncate trailing whitespace in the name. */
-		handle_white_space(asr->rt->ent[i].name, TRUNCATE);
+		handle_white_space(rt->ent[i].name, TRUNCATE);
 	}
 
 	return 1;
@@ -479,11 +486,12 @@
 static int find_toplevel(struct lib_context *lc, struct asr *asr)
 {
 	int i, toplevel = -1;
+	struct asr_raidtable *rt = asr->rt;
 
-	for (i = 0; i < asr->rt->elmcnt; i++) {
-		if (asr->rt->ent[i].raidlevel == FWL)
+	for (i = 0; i < rt->elmcnt; i++) {
+		if (rt->ent[i].raidlevel == FWL)
 			toplevel = i;
-		else if (asr->rt->ent[i].raidlevel == FWL_2) {
+		else if (rt->ent[i].raidlevel == FWL_2) {
 			toplevel = i;
 			break;
 		}
@@ -499,13 +507,14 @@
 static struct asr_raid_configline *find_logical(struct asr *asr)
 {
 	int i, j;
+	struct asr_raidtable *rt = asr->rt;
 
 	/* This MUST be done backwards! */
-	for (i = asr->rt->elmcnt - 1; i > -1; i--) {
-		if (asr->rt->ent[i].raidmagic == asr->rb.drivemagic) {
+	for (i = rt->elmcnt - 1; i > -1; i--) {
+		if (rt->ent[i].raidmagic == asr->rb.drivemagic) {
 			for (j = i - 1; j > -1; j--) {
-				if (asr->rt->ent[j].raidlevel == FWL)
-					return asr->rt->ent + j;
+				if (rt->ent[j].raidlevel == FWL)
+					return rt->ent + j;
 			}
 		}
 	}
@@ -526,7 +535,7 @@
 
 /* Wrapper for name() */
 static char *js_name(struct lib_context *lc, struct raid_dev *rd,
-		     unsigned int subset)
+		     unsigned subset)
 {
 	return name(lc, META(rd, asr));
 }
@@ -694,10 +703,11 @@
 static void delete_configline(struct asr *asr, int index)
 {
 	struct asr_raid_configline *cl, *end;
+	struct asr_raidtable *rt = asr->rt;
 
-	asr->rt->elmcnt--;
-	cl = asr->rt->ent + index;
-	end = asr->rt->ent + asr->rt->elmcnt;
+	rt->elmcnt--;
+	cl = rt->ent + index;
+	end = rt->ent + rt->elmcnt;
 	while (cl < end) {
 		memcpy(cl, cl + 1, sizeof(*cl));
 		++cl;
@@ -707,19 +717,19 @@
 /* Find the newest configline entry in raid set and return a pointer to it. */
 static struct raid_dev *find_newest_drive(struct raid_set *rs)
 {
-	struct asr *asr;
+	struct asr_raidtable *rt;
 	struct raid_dev *device, *newest = NULL;
 	uint16_t newest_raidseq = 0;
         int i;
 	
 	list_for_each_entry(device, &rs->devs, devs) {
-		asr = META(device, asr);
+		rt = META(device, asr)->rt;
 		// FIXME: We should be able to assume each configline
 		// in a single drive has the same raidseq as the rest
 		// in that drive. We're doing too much work here.
-		for (i = 0; i < asr->rt->elmcnt; ++i) {
-			if (asr->rt->ent[i].raidseq >= newest_raidseq) {
-				newest_raidseq = asr->rt->ent[i].raidseq;
+		for (i = 0; i < rt->elmcnt; i++) {
+			if (rt->ent[i].raidseq >= newest_raidseq) {
+				newest_raidseq = rt->ent[i].raidseq;
 				newest = device;
 			}
 		}
@@ -830,24 +840,25 @@
 static int create_configline(struct raid_set *rs, struct asr *asr,
 		             struct asr *a, struct raid_dev* newest)
 {
-	if (asr->rt->elmcnt >= RCTBL_MAX_ENTRIES) {
-		return 0;
-	}
-
-	struct asr *newest_asr;
+	struct asr *newest_asr = META(newest, asr);
 	struct asr_raid_configline *cl;
 	
-	newest_asr = META(newest, asr);
+	if (asr->rt->elmcnt >= RCTBL_MAX_ENTRIES)
+		return 0;
 	
 	cl = asr->rt->ent + asr->rt->elmcnt;
 	asr->rt->elmcnt++;
 
-	/* Use first raidseq, below: FIXME - don't assume all CLS are
-	 * consistent */
+	/*
+	 * Use first raidseq, below: FIXME - don't
+	 * assume all CLS are consistent.
+	 */
 	cl->raidmagic = a->rb.drivemagic;
 	cl->raidseq = newest_asr->rt->ent[0].raidseq;
 	cl->strpsize = newest_asr->rt->ent[0].strpsize;
-	strcpy((char*) cl->name, &rs->name[4]); /* starts after "asr_" */
+
+	/* Starts after "asr_" */
+	strcpy((char*) cl->name, &rs->name[sizeof(HANDLER)]);
 	cl->raidcnt = 0;
 
 	/* Convert rs->type to an ASR_RAID type for the CL */
@@ -875,12 +886,13 @@
 	struct asr_raid_configline *cl;
 	struct raid_dev *d, *newest;
 	struct asr *a;
+	struct asr_raidtable *rt = asr->rt;
 
 	/* Find the raid set */
 	rs = get_raid_set(lc, rd);
 	if (!rs) {
 		/* Array-less disks ... have no CLs ? */
-		asr->rt->elmcnt = 0;
+		rt->elmcnt = 0;
 		return 1;
 	}
 	
@@ -901,14 +913,14 @@
 		struct asr *newest_asr = META(newest, asr);
 	
 		/* copy entire table from newest drive */	
-		asr->rt->elmcnt = newest_asr->rt->elmcnt;
-		memcpy(asr->rt->ent, newest_asr->rt->ent,
-			asr->rt->elmcnt * sizeof(*asr->rt->ent));
+		rt->elmcnt = newest_asr->rt->elmcnt;
+		memcpy(rt->ent, newest_asr->rt->ent,
+			rt->elmcnt * sizeof(*rt->ent));
 	}
 
 	/* Increment the top level CL's raid count */
 	/* Fixme: What about the the FWLs in a FWL2 setting? */
-	cl = asr->rt->ent + find_toplevel(lc, asr);
+	cl = rt->ent + find_toplevel(lc, asr);
 	cl->raidseq++;
 
 	/* For each disk in the rs */
@@ -977,7 +989,7 @@
  */
 
 /* Retrieve the number of devices that should be in this set. */
-static unsigned int device_count(struct raid_dev *rd, void *context)
+static unsigned device_count(struct raid_dev *rd, void *context)
 {
 	/* Get the logical drive */
 	struct asr_raid_configline *cl = find_logical(META(rd, asr));
@@ -1052,10 +1064,10 @@
 /* Dump a raid config table */
 static void dump_rt(struct lib_context *lc, struct asr_raidtable *rt)
 {
-	unsigned int i;
+	unsigned i;
 
 	DP("ridcode:\t\t\t0x%X", rt, rt->ridcode);
-	DP("table ver:\t\t%d", rt, rt->rversion);
+	DP("rversion:\t\t%d", rt, rt->rversion);
 	DP("max configs:\t\t%d", rt, rt->maxelm);
 	DP("configs:\t\t\t%d", rt, rt->elmcnt);
 	DP("config sz:\t\t%d", rt, rt->elmsize);
@@ -1124,7 +1136,6 @@
 
 	if (!cl)
 		LOG_ERR(lc, 0, "%s: Could not find current disk!", handler);		
-
 	/* We need two metadata areas */
 	if (!(ma = rd->meta_areas = alloc_meta_areas(lc, rd, handler, 2)))
 		return 0;
--- dmraid/lib/format/ataraid/isw.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/format/ataraid/isw.c	2008/04/02 13:35:31	1.3
@@ -364,21 +364,26 @@
 {
 	int ret;
 	struct isw *isw = META(rd, isw);
+	int large = div_up(isw->mpb_size, ISW_DISK_BLOCK_SIZE) > 1;
 
 	to_disk(isw, FULL);
 
-	/*
-	 * Copy 1st metadata sector to after the extended ones
-	 * and increment metadata area pointer by one block, so
-	 * that the metadata is filed in the proper sequence.
-	 */
-	memcpy((void*) isw + rd->meta_areas->size, isw, ISW_DISK_BLOCK_SIZE);
-	rd->meta_areas->area += ISW_DISK_BLOCK_SIZE;
+	if (large) {
+		/*
+		 * Copy 1st metadata sector to after the extended ones
+		 * and increment metadata area pointer by one block, so
+		 * that the metadata is filed in the proper sequence.
+		 */
+		memcpy((void*) isw + rd->meta_areas->size, isw,
+		       ISW_DISK_BLOCK_SIZE);
+		rd->meta_areas->area += ISW_DISK_BLOCK_SIZE;
+	}
 
 	ret = write_metadata(lc, handler, rd, -1, erase);
 
 	/* Correct metadata area pointer. */
-	rd->meta_areas->area -= ISW_DISK_BLOCK_SIZE;
+	if (large)
+		rd->meta_areas->area -= ISW_DISK_BLOCK_SIZE;
 
 	to_cpu(isw, FULL);
 
@@ -504,7 +509,7 @@
 
 /* Add an Intel SW RAID device to a set */
 static struct raid_set *isw_group(struct lib_context *lc,
-				    struct raid_dev *rd_meta)
+				  struct raid_dev *rd_meta)
 {
 	struct raid_set *rs_group;
 
@@ -744,7 +749,7 @@
 static struct dmraid_format isw_format = {
 	.name	= HANDLER,
 	.descr	= "Intel Software RAID",
-	.caps	= "0,1",
+	.caps	= "0,1,5",
 	.format = FMT_RAID,
 	.read	= isw_read,
 	.write	= isw_write,
--- dmraid/lib/format/ataraid/jm.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/format/ataraid/jm.c	2008/04/02 13:35:31	1.3
@@ -1,8 +1,8 @@
 /*
  * JMicron metadata format handler.
  *
- * Copyright (C) 2006  Heinz Mauelshagen, Red Hat GmbH.
- *                     All rights reserved.
+ * Copyright (C) 2006,2007  Heinz Mauelshagen, Red Hat GmbH.
+ *                          All rights reserved.
  *
  * See file LICENSE at the top of this source tree for license information.
  */
@@ -25,25 +25,27 @@
 static char *name(struct lib_context *lc, struct raid_dev *rd,
 		  unsigned int subset)
 {
+	int i;
 	size_t len;
 	struct jm *jm = META(rd, jm);
-	char buf[2], *ret, *name = (char *) jm->name;
+	char buf[JM_NAME_LEN + 1], *ret, *name = (char *) jm->name;
 
-	/* Name always 0 terminated ? */
-	if ((len = strlen(name)) > JM_NAME_LEN)
-		len = JM_NAME_LEN;
-
-	len += sizeof(HANDLER) + 2;
-	if (jm->mode == JM_T_RAID01)
-		len++;
+	/* Name always 0 terminated or whitespace at end ? */
+	strncpy(buf, name, JM_NAME_LEN);
+	len = strlen(buf);
+	i = len < JM_NAME_LEN ? len : JM_NAME_LEN;
+	buf[i] = 0;
+	while (i-- && isspace(buf[i]))
+		buf[i] = 0;
 
+	len = strlen(buf) + sizeof(HANDLER) + (jm->mode == JM_T_RAID01 ? 3 : 2);
 	if ((ret = dbg_malloc(len))) {
 		if (jm->mode == JM_T_RAID01 && subset)
 			sprintf(buf, "-%u", member(jm) / 2);
 		else
 			*buf = 0;
 
-		sprintf(ret, "%s_%s%s", HANDLER, name, buf);
+		sprintf(ret, "%s_%s%s", handler, name, buf);
 	}
 
 	return ret;
--- dmraid/lib/format/ataraid/lsi.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/format/ataraid/lsi.c	2008/04/02 13:35:31	1.3
@@ -179,6 +179,10 @@
 {
 	struct lsi *lsi = META(rd, lsi);
 
+	/* Refuse to add drives that are not online */
+	if (get_disk(lsi)->offline)
+		return 0;
+
 	if (!init_raid_set(lc, rs, rd, lsi->stride, type(lsi), handler))
 		return 0;
 
@@ -300,8 +304,8 @@
 		  i, disk->disk_number);
 		P("disks[%u].set_number: %u", lsi, disk->set_number,
 		  i, disk->set_number);
-		P("disks[%u].unknown1: %u, 0x%u", lsi, disk->unknown1,
-		  i, disk->unknown1, disk->unknown1);
+		P("disks[%u].unknown1: %lu, 0x%lX", lsi, disk->unknown1,
+		  i, (uint64_t) disk->unknown1, (uint64_t) disk->unknown1);
 	}
 
 	DP("disk_number: %u", lsi, lsi->disk_number);
--- dmraid/lib/format/ataraid/lsi.h	2008/02/22 16:57:36	1.1
+++ dmraid/lib/format/ataraid/lsi.h	2008/04/02 13:35:31	1.2
@@ -28,7 +28,8 @@
 	uint16_t magic_1;
 	uint8_t disk_number;
 	uint8_t set_number;
-	uint8_t unknown1[8];
+	uint8_t offline;
+	uint8_t unknown1[7];
 } __attribute__ ((packed));
 
 struct lsi {
@@ -47,8 +48,10 @@
 	uint8_t dummy4;		/* 0x11 */
 	uint16_t stride;		/* 0x12 - 0x13 */
 	uint8_t filler[0x20-0x14];	/* 0x14 - 0x1F */
+
 #define	LSI_MAX_DISKS	4
 	struct lsi_disk disks[LSI_MAX_DISKS];/* 0x20 - 0x5F */
+
 #define	LSI_DISK(lsi)		(lsi->set_number * 2 + lsi->disk_number)
 #define LSI_MAGIC_0(lsi)	(lsi->disks[LSI_DISK(lsi)].magic_0)
 #define LSI_MAGIC_1(lsi)	(lsi->disks[LSI_DISK(lsi)].magic_1)
--- dmraid/lib/format/ataraid/nv.c	2008/02/22 17:04:35	1.2
+++ dmraid/lib/format/ataraid/nv.c	2008/04/02 13:35:31	1.3
@@ -155,7 +155,7 @@
 	CVT32(nv->unitFlags);
 	CVT32(array->version);
 
-	while (i--);
+	while (i--)
 		CVT32(array->signature[i]);
 
 	CVT32(array->raidLevel);
--- dmraid/lib/format/ataraid/pdc.c	2008/02/22 17:06:00	1.3
+++ dmraid/lib/format/ataraid/pdc.c	2008/04/02 13:35:31	1.4
@@ -1,7 +1,7 @@
 /*
  * Promise FastTrak ATARAID metadata format handler.
  *
- * Copyright (C) 2004,2005  Heinz Mauelshagen, Red Hat GmbH.
+ * Copyright (C) 2004-2008  Heinz Mauelshagen, Red Hat GmbH.
  *                          All rights reserved.
  *
  * See file LICENSE at the top of this source tree for license information.
@@ -27,26 +27,25 @@
 /*
  * Make up Promise RAID device name.
  */
-static unsigned int set_number(struct pdc *pdc)
+static unsigned set_number(struct pdc *pdc)
 {
 	return pdc->raid.disk_number >= (pdc->raid.total_disks / 2);
 }
 
-static size_t _name(struct pdc *pdc, char *str, size_t len, int subset)
+static size_t __name(struct pdc *pdc, char *str, size_t len, int subset)
 {
 	return snprintf(str, len, subset ? "pdc_%u-%u" : "pdc_%u",
 			pdc->raid.magic_1, set_number(pdc));
 }
 
-static char *name(struct lib_context *lc, struct raid_dev *rd,
-		  unsigned int subset)
+static char *_name(struct lib_context *lc, struct pdc *pdc,
+		  unsigned subset)
 {
-	struct pdc *pdc = META(rd, pdc);
 	size_t len;
 	char *ret = NULL;
 
-	if ((ret = dbg_malloc((len = _name(pdc, ret, 0, subset) + 1)))) {
-		_name(pdc, ret, len, subset);
+	if ((ret = dbg_malloc((len = __name(pdc, ret, 0, subset) + 1)))) {
+		__name(pdc, ret, len, subset);
 		mk_alpha(lc, ret + HANDLER_LEN,
 			 len - HANDLER_LEN - (subset ? 2 : 0));
 	} else
@@ -55,6 +54,12 @@
 	return ret;
 }
 
+static char *name(struct lib_context *lc, struct raid_dev *rd,
+		  unsigned subset)
+{
+	return _name(lc, META(rd, pdc), subset);
+}
+
 /*
  * Retrieve status of device.
  *
@@ -87,13 +92,13 @@
 	if (is_raid10(pdc))
 		pdc->raid.type = PDC_T_RAID10;
 
-	return rd_type(types, (unsigned int) pdc->raid.type);
+	return rd_type(types, (unsigned) pdc->raid.type);
 }
 
 /* Calculate checksum on Promise metadata. */
 static uint32_t checksum(struct pdc *pdc)
 {
-	unsigned int i = 511, sum = 0;
+	unsigned i = 511, sum = 0;
 	uint32_t *p = (uint32_t*) pdc;
 
 	while (i--)
@@ -133,32 +138,79 @@
 }
 #endif
 
+/* Check for Promis signature. */
+static int is_signature(struct pdc *pdc)
+{
+	return !strncmp((const char*) pdc->promise_id,
+			PDC_MAGIC, PDC_ID_LENGTH);
+}
+
 /* Read and try to discover Promise signature. */
 static void *pdc_read_metadata(struct lib_context *lc, struct dev_info *di,
 			       size_t *size, uint64_t *offset,
 			       union read_info *info)
 {
+	struct pdc *ret;
+	unsigned ma, sub;
+	unsigned pdc_sectors_max = di->sectors - div_up(sizeof(*ret), 512);
+
 	/* Assume certain sectors off the end of the RAID device. */
-	static unsigned int *s, sectors[] = {
+	static unsigned end_sectors[] = {
 		PDC_CONFIGOFFSETS, 0,
 	};
-	struct pdc *ret;
+	/* ...or beginning of large RAID device. */
+	static unsigned begin_sectors[] = {
+		268435377, 0,
+	};
+	unsigned *s = end_sectors;
+	uint64_t sector;
 
-	if ((ret = alloc_private(lc, handler, sizeof(*ret)))) {
-		for (s = sectors; *s; s++) {
-			if (read_file(lc, handler, di->path, ret, sizeof(*ret),
-				      (di->sectors - *s) << 9) &&
-			    !strncmp((const char*) ret->promise_id, PDC_MAGIC,
-				     PDC_ID_LENGTH)) {
-				info->u32 = *s;
-				return (void*) ret;
+	if (!(ret = alloc_private(lc, handler,
+				  PDC_MAX_META_AREAS * sizeof(*ret))))
+		return NULL;
+
+	info->u32 = 0;
+	sub = 1;
+	do {
+		/* Check all sector offsets for metadata signature. */
+		for (; *s && !info->u32; s++) {
+			sector = sub ? di->sectors - *s : *s;
+	
+			/* ...and all possible optional metadata signatures. */
+			for (ma = 0;
+			     ma < PDC_MAX_META_AREAS &&
+			     sector <= pdc_sectors_max;
+			     ma++, sector += PDC_META_OFFSET) {
+				if (read_file(lc, handler, di->path,
+					      ret + ma, sizeof(*ret),
+					      sector << 9)) {
+					/* No signature? */
+					if (!is_signature(ret + ma)) {
+						if (info->u32)
+							goto out;
+						else
+							break;
+
+					/* Memorize main metadata sector. */
+					} else if (!info->u32)
+						info->u32 = *s;
+				}
 			}
 		}
 
+		/* Retry relative to beginning of device if none... */
+		if (!info->u32)
+			s = begin_sectors;
+	} while (!info->u32 && sub--);
+
+   out:
+	/* No metadata signature(s) found. */
+	if (!info->u32) {
 		dbg_free(ret);
+		ret = NULL;
 	}
 
-	return NULL;
+	return ret;
 }
 
 /* Magic check. */
@@ -224,7 +276,7 @@
 /*
  * Group the RAID disk into a Promise set.
  */
-static unsigned int stride(struct pdc *pdc)
+static unsigned stride(struct pdc *pdc)
 {
 	return pdc->raid.raid0_shift ? 1 << pdc->raid.raid0_shift : 0;
 }
@@ -235,12 +287,85 @@
 	super->stride = stride(META((private), pdc));
 }
 
-/* Add a PDC RAID device to a set. */
-static int group_rd(struct lib_context *lc, struct raid_set *rs,
-		    struct raid_set **ss, struct raid_dev *rd)
+/* Calculate RAID device size in sectors depending on RAID type. */
+static uint64_t sectors(struct raid_dev *rd, unsigned meta_sector)
 {
 	struct pdc *pdc = META(rd, pdc);
 
+	switch (pdc->raid.type) {
+	case PDC_T_RAID10:
+               return pdc->raid.total_secs / (pdc->raid.total_disks / 2);
+
+	case PDC_T_RAID1:
+               return pdc->raid.total_secs;
+
+	case PDC_T_RAID0:
+               return pdc->raid.total_secs / pdc->raid.total_disks;
+
+	case PDC_T_SPAN:
+	       return rd->di->sectors - meta_sector;
+	}
+
+	return 0;
+}
+
+static struct raid_dev *_create_rd(struct lib_context *lc, struct raid_dev *rd,
+				   struct pdc *pdc, unsigned idx)
+{
+	struct raid_dev *r;
+
+	if (!is_pdc(lc, rd->di, pdc) ||
+	    !(r = alloc_raid_dev(lc, handler)))
+		return NULL;
+
+	if ((r->type = type(pdc)) == t_undef) {
+		log_err(lc, "%s: RAID type %u not supported",
+			handler, (unsigned) pdc->raid.type);
+		goto bad_free;
+	}
+
+        if (!(r->name = _name(lc, pdc, is_raid10(pdc))))
+		goto bad_free;
+
+	/* Allocate meta_areas for devices() to work. */
+	if (!(r->meta_areas = alloc_meta_areas(lc, r, handler, 1)))
+		goto bad_free;
+
+	/* Allocate private metadata area so that free_raid_dev() succeeds. */
+	r->meta_areas->area = alloc_private(lc, handler, sizeof(*pdc));
+	if (!r->meta_areas->area)
+		goto bad_free;
+
+	memcpy(r->meta_areas->area, pdc, sizeof(*pdc));
+	r->meta_areas->size = sizeof(*pdc);
+	r->meta_areas->offset = rd->meta_areas->offset + idx * PDC_META_OFFSET;
+
+	r->di = rd->di;
+	r->fmt = rd->fmt;
+	r->status = status(pdc);
+
+	/*
+	 * Type needs to be set before sectors(), because we need
+	 * to set the RAID10 type used there!
+	 */
+	r->type = type(pdc);
+
+	r->offset = pdc->raid.start;
+	if ((r->sectors = sectors(r, 0)))
+		goto out;
+
+	log_zero_sectors(lc, r->di->path, handler);
+
+   bad_free:
+	free_raid_dev(lc, &r);
+   out:
+	return r;
+}
+
+/* Add a PDC RAID device to a set. */
+static int _group_rd(struct lib_context *lc, struct raid_set *rs,
+		    struct raid_set **ss, struct raid_dev *rd, struct pdc *pdc)
+{
 	if (!init_raid_set(lc, rs, rd, stride(pdc), pdc->raid.type, handler))
 		return 0;
 
@@ -271,6 +396,52 @@
 	return 1;
 }
 
+static inline unsigned count_meta_areas(struct pdc *pdc)
+{
+	unsigned r;
+
+	/* Count metadata signatures discovered by pdc_read_metadata(). */
+	for (r = 0; r < PDC_MAX_META_AREAS; r++) {
+		if (!is_signature(pdc + r))
+			break;
+	}
+
+	return r;
+}
+
+/* FIXME: different super sets possible with multiple metadata areas ? */
+static int group_rd(struct lib_context *lc, struct raid_set *rs,
+		    struct raid_set **ss, struct raid_dev *rd)
+{
+	int r;
+	struct pdc *pdc = META(rd, pdc);
+	unsigned idx = 0, ma = count_meta_areas(pdc);
+	struct raid_dev *rd_tmp;
+	struct raid_set *rs_tmp;
+
+
+	/* Group the one we already have. */
+	r = _group_rd(lc, rs, ss, rd, META(rd, pdc));
+
+	/* Group any additional ones. */
+	while (r && --ma) {
+		if (!(rd_tmp = _create_rd(lc, rd, ++pdc, ++idx)))
+			return 0;
+
+		if (!(rs_tmp = find_or_alloc_raid_set(lc, rd_tmp->name,
+						      FIND_ALL, rd_tmp,
+						      NO_LIST, NO_CREATE,
+						      NO_CREATE_ARG))) {
+			free_raid_dev(lc, &rd_tmp);
+			return 0;
+		}
+
+		r = _group_rd(lc, rs_tmp, ss, rd_tmp, pdc);
+	}
+
+	return r;
+}
+
 static struct raid_set *pdc_group(struct lib_context *lc, struct raid_dev *rd)
 {
 	struct raid_set *rs, *ss = NULL;
@@ -290,7 +461,7 @@
  *
  * FIXME: more sanity checks.
  */
-static unsigned int devices(struct raid_dev *rd, void *context)
+static unsigned devices(struct raid_dev *rd, void *context)
 {
 	struct pdc *pdc = META(rd, pdc);
 
@@ -344,30 +515,38 @@
 
 #ifdef DMRAID_NATIVE_LOG
 /* Log native information about a Promise RAID device. */
-static void pdc_log(struct lib_context *lc, struct raid_dev *rd)
+static void _pdc_log(struct lib_context *lc, struct dev_info *di,
+		     struct pdc *pdc)
 {
-	unsigned int i;
-	struct pdc *pdc = META(rd, pdc);
+	unsigned i;
 	struct pdc_disk *disk;
 
-	log_print(lc, "%s (%s):", rd->di->path, handler);
+	log_print(lc, "%s (%s):", di->path, handler);
 	DP("promise_id: \"%s\"", pdc, pdc->promise_id);
-	DP("unknown_0: 0x%x", pdc, pdc->unknown_0);
+	P("unknown_0: 0x%x %u",
+	  pdc, pdc->unknown_0, pdc->unknown_0, pdc->unknown_0);
 	DP("magic_0: 0x%x", pdc, pdc->magic_0);
-	DP("unknown_1: 0x%x", pdc, pdc->unknown_1);
+	P("unknown_1: 0x%x %u",
+	  pdc, pdc->unknown_1, pdc->unknown_1, pdc->unknown_1);
 	DP("magic_1: 0x%x", pdc, pdc->magic_1);
-	DP("unknown_2: 0x%x", pdc, pdc->unknown_2);
+	P("unknown_2: 0x%x %u",
+	  pdc, pdc->unknown_2, pdc->unknown_2, pdc->unknown_2);
 	DP("raid.flags: 0x%x", pdc, pdc->raid.flags);
-	DP("raid.unknown_0: 0x%x", pdc, pdc->raid.unknown_0);
+	P("raid.unknown_0: 0x%x %d",
+	  pdc, pdc->raid.unknown_0, pdc->raid.unknown_0, pdc->raid.unknown_0);
 	DP("raid.disk_number: %u", pdc, pdc->raid.disk_number);
 	DP("raid.channel: %u", pdc, pdc->raid.channel);
 	DP("raid.device: %u", pdc, pdc->raid.device);
 	DP("raid.magic_0: 0x%x", pdc, pdc->raid.magic_0);
-	DP("raid.unknown_1: 0x%x", pdc, pdc->raid.unknown_1);
-	DP("raid.unknown_2: 0x%x", pdc, pdc->raid.unknown_2);
+	P("raid.unknown_1: 0x%x %u",
+	   pdc, pdc->raid.unknown_1, pdc->raid.unknown_1, pdc->raid.unknown_1);
+	P("raid.start: 0x%x %u",
+	  pdc, pdc->raid.start, pdc->raid.start, pdc->raid.start);
 	DP("raid.disk_secs: %u", pdc, pdc->raid.disk_secs);
-	DP("raid.unknown_3: 0x%x", pdc, pdc->raid.unknown_3);
-	DP("raid.unknown_4: 0x%x", pdc, pdc->raid.unknown_4);
+	P("raid.unknown_3: 0x%x %u",
+	  pdc, pdc->raid.unknown_3, pdc->raid.unknown_3, pdc->raid.unknown_3);
+	P("raid.unknown_4: 0x%x %u",
+	  pdc, pdc->raid.unknown_4, pdc->raid.unknown_4, pdc->raid.unknown_4);
 	DP("raid.status: 0x%x", pdc, pdc->raid.status);
 	DP("raid.type: 0x%x", pdc, pdc->raid.type);
 	DP("raid.total_disks: %u", pdc, pdc->raid.total_disks);
@@ -379,7 +558,8 @@
 	DP("raid.heads: %u", pdc, pdc->raid.heads);
 	DP("raid.sectors: %u", pdc, pdc->raid.sectors);
 	DP("raid.magic_1: 0x%x", pdc, pdc->raid.magic_1);
-	DP("raid.unknown_5: 0x%x", pdc, pdc->raid.unknown_5);
+	P("raid.unknown_5: 0x%x %u",
+	  pdc, pdc->raid.unknown_5, pdc->raid.unknown_5, pdc->raid.unknown_5);
 
 	for (disk = pdc->raid.disk, i = 0;
 	     i < pdc->raid.total_disks;
@@ -394,6 +574,11 @@
 	P("checksum: 0x%x %s", pdc, pdc->checksum, pdc->checksum,
 	   checksum(pdc) ? "Ok" : "BAD");
 }
+
+static void pdc_log(struct lib_context *lc, struct raid_dev *rd)
+{
+	_pdc_log(lc, rd->di, META(rd, pdc));
+}
 #endif
 
 static struct dmraid_format pdc_format = {
@@ -417,33 +602,11 @@
 	return register_format_handler(lc, &pdc_format);
 }
 
-/* Calculate RAID device size in sectors depending on RAID type. */
-static uint64_t sectors(struct raid_dev *rd, unsigned int meta_sector)
-{
-	struct pdc *pdc = META(rd, pdc);
-
-	switch (pdc->raid.type) {
-	case PDC_T_RAID10:
-               return pdc->raid.total_secs / (pdc->raid.total_disks / 2);
-
-	case PDC_T_RAID1:
-               return pdc->raid.total_secs;
-
-	case PDC_T_RAID0:
-               return pdc->raid.total_secs / pdc->raid.total_disks;
-
-	case PDC_T_SPAN:
-	       return rd->di->sectors - meta_sector;
-	}
-
-	return 0;
-}
-
 /* Set the RAID device contents up derived from the PDC ones */
 static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
 		    struct dev_info *di, void *meta, union read_info *info)
 {
-	unsigned int meta_sector;
+	unsigned meta_sector;
 	struct pdc *pdc = meta;
 
 	if (!checksum(pdc))
@@ -455,21 +618,21 @@
 	meta_sector = info->u32;
 	rd->meta_areas->offset = di->sectors - meta_sector;
 	rd->meta_areas->size = sizeof(*pdc);
-	rd->meta_areas->area = (void*) pdc;
+	rd->meta_areas->area = pdc;
 
         rd->di = di;
 	rd->fmt = &pdc_format;
-
 	rd->status = status(pdc);
+
 	/*
 	 * Type needs to be set before sectors(), because we need
 	 * to set the RAID10 type used there!
 	 */
-	rd->type   = type(pdc);
+	rd->type = type(pdc);
 
 	rd->offset = PDC_DATAOFFSET;
 	if (!(rd->sectors = sectors(rd, meta_sector)))
 		return log_zero_sectors(lc, di->path, handler);
 
-        return (rd->name = name(lc, rd, is_raid10(pdc))) ? 1 : 0;
+        return (rd->name = _name(lc, pdc, is_raid10(pdc))) ? 1 : 0;
 }
--- dmraid/lib/format/ataraid/pdc.h	2008/02/22 16:57:36	1.1
+++ dmraid/lib/format/ataraid/pdc.h	2008/04/02 13:35:31	1.2
@@ -13,9 +13,16 @@
 
 #include <stdint.h>
 
-#define PDC_CONFIGOFFSETS	63,255,256,16,399,735
+#define PDC_CONFIGOFFSETS	63,255,256,16,399,675,735,974,991
 #define	PDC_DATAOFFSET 0
 
+/*
+ * Maximum metadata areas checked for and offset of
+ * those relative to PDC_CONFIGOFFSETS value in sectors.
+ */
+#define	PDC_MAX_META_AREAS	4
+#define	PDC_META_OFFSET		14
+
 /* Ondisk metadata for Promise Fastrack */
 struct pdc {
 #define PDC_ID_LENGTH	24
@@ -36,7 +43,8 @@
 		uint8_t device;			/* 0x207 */
 		uint32_t magic_0;		/* 0x208 - 0x20B */
 		uint32_t unknown_1;		/* 0x20C - 0x20F */
-		uint32_t unknown_2;		/* 0x210 - 0x213 */
+		// uint32_t unknown_2;		/* 0x210 - 0x213 */
+		uint32_t start;			/* 0x210 - 0x213 */
 		uint32_t disk_secs;		/* 0x214 - 0x217 */
 		uint32_t unknown_3;		/* 0x218 - 0x21B */
 		uint16_t unknown_4;		/* 0x21C - 0x21D */
--- dmraid/lib/format/ddf/ddf1.c	2008/02/22 17:06:54	1.2
+++ dmraid/lib/format/ddf/ddf1.c	2008/04/02 13:35:31	1.3
@@ -19,6 +19,18 @@
 #include "ddf1_cvt.h"
 #include "ddf1_dump.h"
 
+#define GRP_RD(rd) \
+	(((struct ddf1_group_info *) (rd)->private.ptr)->rd_group)
+
+/*
+ * Helper struct to squirrel a group set reference to the check method
+ * in order to avoid, that premature deallocation in metadata.c
+ * removes the group set.
+ */
+struct ddf1_group_info {
+	struct raid_dev *rd_group;
+};
+
 static const char *handler = HANDLER;
 
 #define	DDF1_SPARES	".ddf1_spares"
@@ -595,8 +607,10 @@
 /* Sort DDF1 devices by offset entry within a RAID set. */
 static int dev_sort(struct list_head *pos, struct list_head *new)
 {
-	return compose_id(META(RD(new)->private.ptr, ddf1), RD(new)) <
-	       compose_id(META(RD(pos)->private.ptr, ddf1), RD(pos));
+	struct raid_dev *rd_pos = RD(pos), *rd_new = RD(new);
+
+	return compose_id(META(GRP_RD(rd_new), ddf1), rd_new) <
+	       compose_id(META(GRP_RD(rd_pos), ddf1), rd_pos);
 }
 
 /*
@@ -705,6 +719,7 @@
 	struct raid_dev *rd;
 	struct ddf1_config_record *cr;
 	struct ddf1_phys_drive *pd;
+	struct ddf1_group_info *gi;
 	unsigned int devs, i;
 	
 	if (!(pd = get_phys_drive(ddf1)))
@@ -746,8 +761,14 @@
 			return NULL;
 		}
 
+		if (!(gi = alloc_private(lc, handler, sizeof(*gi)))) {
+			free_raid_dev(lc, &rd);
+			return NULL;
+		}
+
 		/* Keep reference to the entire device for ddf1_check() */
-		rd->private.ptr = rd_group;
+		rd->private.ptr = gi;
+		GRP_RD(rd) = rd_group;
 
 		/* Add rest of subset state */
 		rs->stride = stride(cr);
@@ -825,13 +846,8 @@
 {
 	/* Get the logical drive */
 	struct ddf1_config_record *cr =
-		get_this_config(META(rd->private.ptr, ddf1), rd->offset);
+		get_this_config(META(GRP_RD(rd), ddf1), rd->offset);
 
-	/*
-	 * Release reference after check, so that core
-	 * doesn't try to free it multiple times.
-	 */
-	rd->private.ptr = NULL;
 	return cr ? cr->primary_element_count : 0;
 }
 
--- dmraid/lib/format/ddf/ddf1_crc.c	2008/02/22 17:06:54	1.2
+++ dmraid/lib/format/ddf/ddf1_crc.c	2008/04/02 13:35:31	1.3
@@ -16,6 +16,7 @@
 #include "ddf1.h"
 #include "ddf1_crc.h"
 #include "ddf1_lib.h"
+#include "zlib.h"
 
 #define DM_BYTEORDER_SWAB
 #include <datastruct/byteorder.h>
--- dmraid/lib/format/partition/dos.c	2008/02/22 17:04:36	1.2
+++ dmraid/lib/format/partition/dos.c	2008/04/02 13:35:31	1.3
@@ -29,8 +29,11 @@
 		    unsigned short partition, char *str, size_t len,
 		    unsigned char type)
 {
-	return snprintf(str, len, type ? "%s%u" : "%s",
-			get_basename(lc, rd->di->path), partition);
+	const char *base = get_basename(lc, rd->di->path);
+
+	return type ? snprintf(str, len, "%s%s%u", base, OPT_STR_PARTCHAR(lc),
+			       partition) :
+		      snprintf(str, len, "%s", base);
 }
 
 static char *name(struct lib_context *lc, struct raid_dev *rd,
--- dmraid/lib/metadata/metadata.c	2008/02/22 17:06:00	1.3
+++ dmraid/lib/metadata/metadata.c	2008/04/02 13:35:31	1.4
@@ -799,8 +799,21 @@
 
 		if (len2 > len1 ||
 		    strncmp(rs->name, name, min(len1, len2))) {
+			struct dmraid_format *fmt = get_format(rs);
+
 			log_notice(lc, "dropping unwanted RAID set \"%s\"",
 				   rs->name);
+
+			/*
+			 * ddf1 carries a private pointer to it's contianing
+			 * set which is cleared as part of the check. So we
+			 * must call it's check method before freeing the
+			 * set. Whats more, it looks like ddf1 check can
+			 * only be called once, yoweee !!!!
+			 */
+			if (fmt)
+				fmt->check(lc, rs);
+
 			free_raid_set(lc, rs);
 		}
 	}
@@ -838,6 +851,7 @@
 	struct dmraid_format *fmt;
 
 	list_for_each_safe(elem, tmp, LC_RS(lc)) {
+		/* Some metadata format handlers may not have a check method. */
 		if (!(fmt = get_format((rs = RS(elem)))))
 			continue;
 
@@ -864,11 +878,13 @@
 {
 	struct raid_dev *rd;
 	struct raid_set *rs;
+	struct list_head *elem, *tmp;
 
 	if (name && find_set(lc, NULL, name, FIND_TOP))
 		LOG_ERR(lc, 0, "RAID set %s already exists", name);
 
-	list_for_each_entry(rd, LC_RD(lc), list) {
+	list_for_each_safe(elem, tmp, LC_RD(lc)) {
+		rd = list_entry(elem, struct raid_dev, list);
 		/* FIXME: optimize dropping of unwanted RAID sets. */
 		if ((rs = dmraid_group(lc, rd))) {
 			log_notice(lc, "added %s to RAID set \"%s\"",
@@ -1039,22 +1055,20 @@
  * File RAID metadata and offset on device for analysis.
  */
 /* FIXME: all files into one directory ? */
-static size_t __name(struct lib_context *lc, char *str, size_t len, char *path,
-		     const char *suffix, const char *handler)
+static size_t __name(struct lib_context *lc, char *str, size_t len,
+		     const char *path, const char *suffix)
 {
-	return snprintf(str, len, "%s_%s.%s",
-			get_basename(lc, path), handler, suffix) + 1;
+	return snprintf(str, len, "%s.%s",
+			get_basename(lc, (char*) path), suffix) + 1;
 }
 
-static char *_name(struct lib_context *lc, char *path,
-		  const char *suffix, const char *handler)
+static char *_name(struct lib_context *lc, const char *path, const char *suffix)
 {
 	size_t len;
 	char *ret;
 
-	if ((ret = dbg_malloc((len = __name(lc, NULL, 0, path,
-					    suffix, handler)))))
-		__name(lc, ret, len, path, suffix, handler);
+	if ((ret = dbg_malloc((len = __name(lc, NULL, 0, path, suffix)))))
+		__name(lc, ret, len, path, suffix);
 	else
 		log_alloc_err(lc, __func__);
 
@@ -1067,7 +1081,7 @@
 	int ret = 0;
 	char *name;
 
-	if ((name = _name(lc, path, "dat", handler))) {
+	if ((name = _name(lc, path, "dat"))) {
 		log_notice(lc, "writing metadata file \"%s\"", name);
 		ret = write_file(lc, handler, name, data, size, 0);
 		dbg_free(name);
@@ -1081,25 +1095,64 @@
 {
 	char *name, s_number[32];
 	
-	if ((name = _name(lc, path, suffix, handler))) {
+	if ((name = _name(lc, path, suffix))) {
 		log_notice(lc, "writing %s to file \"%s\"", suffix, name);
 		write_file(lc, handler, name, (void*) s_number,
 		           snprintf(s_number, sizeof(s_number),
-			   "%" PRIu64 "\n", number),
-				 0);
+			   "%" PRIu64 "\n", number), 0);
 		dbg_free(name);
 	}
 }
 
+static int _chdir(struct lib_context *lc, const char *dir)
+{
+	if (chdir(dir)) {
+		log_err(lc, "changing directory to %s", dir);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static char *_dir(struct lib_context *lc, const char *handler)
+{
+	char *dir = _name(lc, lc->cmd, handler);
+
+	if (!dir) {
+		log_err(lc, "allocating directory name for %s", handler);
+		return NULL;
+	}
+
+	if (!mk_dir(lc, dir))
+		goto out;
+
+	if (!_chdir(lc, dir))
+		return dir;
+
+   out:
+	dbg_free(dir);
+	return NULL;
+}
+
 /*
  * File vendor RAID metadata.
  */
 void file_metadata(struct lib_context *lc, const char *handler,
 		   char *path, void *data, size_t size, uint64_t offset)
 {
-	if (OPT_DUMP(lc) &&
-	    file_data(lc, handler, path, data, size))
-		file_number(lc, handler, path, offset, "offset");
+	if (OPT_DUMP(lc)) {
+		char *dir = _dir(lc, handler);
+
+		if (dir)
+			dbg_free(dir);
+		else
+			return;
+
+		if (file_data(lc, handler, path, data, size))
+			file_number(lc, handler, path, offset, "offset");
+
+		_chdir(lc, "..");
+	}
 }
 
 /*
@@ -1108,6 +1161,15 @@
 void file_dev_size(struct lib_context *lc, const char *handler,
 		   struct dev_info *di)
 {
-	if (OPT_DUMP(lc))
+	if (OPT_DUMP(lc)) {
+		char *dir = _dir(lc, handler);
+
+		if (dir)
+			dbg_free(dir);
+		else
+			return;
+
 		file_number(lc, handler, di->path, di->sectors, "size");
+		_chdir(lc, "..");
+	}
 }
--- dmraid/lib/misc/lib_context.c	2008/02/22 16:57:36	1.1
+++ dmraid/lib/misc/lib_context.c	2008/04/02 13:35:32	1.2
@@ -94,6 +94,9 @@
 {
 	lc_inc_opt(lc, LC_SEPARATOR);
 	lc->options[LC_SEPARATOR].arg.str = dbg_strdup((char*) ",");
+
+	lc_inc_opt(lc, LC_PARTCHAR);
+	lc->options[LC_PARTCHAR].arg.str = dbg_strdup((char*) "p");
 }
 
 static void init_cmd(struct lib_context *lc, void *arg)
--- dmraid/man/dmraid.8	2008/02/22 16:57:37	1.1
+++ dmraid/man/dmraid.8	2008/04/02 13:35:32	1.2
@@ -6,6 +6,7 @@
  {-a|--activate} {y|n|yes|no} 
  [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking]
  [-f|--format FORMAT[,FORMAT...]]
+ [{-P|--partchar} CHAR]
  [-p|--no_partitions]
  [--separator SEPARATOR]
  [-t|--test]
@@ -176,6 +177,10 @@
 is restricted to those listed.
 
 .TP
+.I [{-P|--partchar} CHAR]
+Use CHAR as the separator between the device name and the partition number.
+
+.TP
 .I {-r|--raid_devices} [device-path...]
 List all discovered RAID devices with format, RAID level, sectors used
 and data offset into the device.
@@ -187,10 +192,11 @@
 .B -D
 is added to
 .B -r
-the RAID metadata gets dumped into files named devicename_formatname.dat.
-The offset in sectors where the metadata is located on the device is written
-into files named devicename_formatname.offset and the size of the device
-into files named devicename_formatname.size.
+the RAID metadata gets dumped into a subdirectory named dmraid.format_name
+(eg. format_name = isw) in files named devicename.dat.
+The byte offset where the metadata is located on the device is written
+into files named devicename.offset and the size of the device in sectors
+into files named devicename.size.
 
 If 
 .B -E
@@ -214,7 +220,7 @@
 .br
 do
 .br
-	dd if=$f of=/dev/${f%%_*} \\
+	dd if=$f of=/dev/${f%%.dat} \\
 .br
 	seek=`cat ${f%%dat}offset` bs=1
 .br
--- dmraid/tools/VERSION	2008/02/22 17:06:54	1.4
+++ dmraid/tools/VERSION	2008/04/02 13:35:32	1.5
@@ -1 +1 @@
-1.0.0.rc14 (2006.11.08)
+1.0.0.rc15 (2008.04.02)
--- dmraid/tools/commands.c	2008/02/22 16:57:37	1.1
+++ dmraid/tools/commands.c	2008/04/02 13:35:32	1.2
@@ -24,7 +24,7 @@
 /*
  * Command line options.
  */
-static char const *short_opts = "a:hip"
+static char const *short_opts = "a:hipP:"
 #ifndef	DMRAID_MINI
 				"bc::dDEf:gl"
 #ifdef	DMRAID_NATIVE_LOG
@@ -38,6 +38,7 @@
 static struct option long_opts[] = {
 	{"activate", required_argument, NULL, 'a'},
 	{"format", required_argument, NULL, 'f'},
+	{"partchar", required_argument, NULL, 'P'},
 	{"no_partitions", no_argument, NULL, 'p'},
 # ifndef DMRAID_MINI
 	{"block_devices", no_argument, NULL, 'b'},
@@ -148,6 +149,14 @@
 }
 #endif
 
+/* Check and store option for partition separator. */
+static int check_part_separator(struct lib_context *lc, int arg)
+{
+	/* We're not actually checking that it's only one character... if
+	   somebody wants to use more, it shouldn't hurt anything. */
+	return lc_stralloc_opt(lc, LC_PARTCHAR, optarg) ? 1 : 0;
+}
+
 /* Display help information */
 static int help(struct lib_context *lc, int arg)
 {
@@ -158,6 +167,7 @@
 		  "[Early Boot Version]\n", c);
 	log_print(lc, "%s\t{-a|--activate} {y|n|yes|no} [-i|--ignorelocking]\n"
 		  "\t[-f|--format FORMAT[,FORMAT...]]\n"
+		  "\t[-P|--partchar CHAR]\n"
 		  "\t[-p|--no_partitions]\n"
 		  "\t[--separator SEPARATOR]\n"
 		  "\t[RAID-set...]\n", c);
@@ -168,6 +178,7 @@
 	log_print(lc, "* = [-d|--debug]... [-v|--verbose]... [-i|--ignorelocking]\n");
 	log_print(lc, "%s\t{-a|--activate} {y|n|yes|no} *\n"
 		  "\t[-f|--format FORMAT[,FORMAT...]]\n"
+		  "\t[-P|--partchar CHAR]\n"
 		  "\t[-p|--no_partitions]\n"
 		  "\t[--separator SEPARATOR]\n"
 		  "\t[-t|--test]\n"
@@ -249,6 +260,19 @@
 	  LC_FORMAT,
 	},
 
+	/* Partition separator. */
+	{ 'P',
+	  PARTCHAR,
+	  ACTIVATE|DEACTIVATE,
+	  FORMAT|HELP|IGNORELOCKING|SEPARATOR
+#ifndef DMRAID_MINI
+	  |DBG|TEST|VERBOSE
+#endif
+	  , ARGS,
+	  check_part_separator,
+	  0,
+	},
+
 	/* Partition option. */
 	{ 'p',
 	  NOPARTITIONS,
--- dmraid/tools/commands.h	2008/02/22 16:57:37	1.1
+++ dmraid/tools/commands.h	2008/04/02 13:35:32	1.2
@@ -46,6 +46,7 @@
 #endif
 	VERSION		= 0x100000,
 	IGNORELOCKING	= 0x200000,
+	PARTCHAR	= 0x400000,
 };
 
 #define	ALL_FLAGS	((enum action) -1)




More information about the dm-devel mailing list