Index: sys/geom/geom_ccd.c
===================================================================
RCS file: /lhome/CVS-FreeBSD/src/sys/geom/geom_ccd.c,v
retrieving revision 1.154
diff -u -r1.154 geom_ccd.c
--- sys/geom/geom_ccd.c	7 Apr 2006 16:19:48 -0000	1.154
+++ sys/geom/geom_ccd.c	13 Apr 2006 19:47:45 -0000
@@ -72,6 +72,8 @@
 /* sc_flags */
 #define CCDF_UNIFORM	0x02	/* use LCCD of sizes for uniform interleave */
 #define CCDF_MIRROR	0x04	/* use mirroring */
+#define CCDF_NO_OFFSET	0x08	/* do not leave space in front */
+#define CCDF_LINUX	0x10	/* use Linux compatibility mode */
 
 /* Mask of user-settable ccd flags. */
 #define CCDF_USERMASK	(CCDF_UNIFORM|CCDF_MIRROR)
@@ -136,6 +138,7 @@
 	u_int32_t	 sc_secsize;		/* # bytes per sector */
 	int		 sc_pick;		/* side of mirror picked */
 	daddr_t		 sc_blk[2];		/* mirror localization */
+	u_int32_t	 sc_offset;		/* actual offset used */
 };
 
 static g_start_t g_ccd_start;
@@ -215,6 +218,20 @@
 
 	maxsecsize = 0;
 	minsize = 0;
+
+	if (cs->sc_flags & CCDF_LINUX) {
+		cs->sc_offset = 0;
+		cs->sc_ileave *= 2;
+		if (cs->sc_flags & CCDF_MIRROR && cs->sc_ndisks != 2)
+			gctl_error(req, "Mirror mode for Linux raids is "
+			                "only supported with 2 devices");
+	} else {
+		if (cs->sc_flags & CCDF_NO_OFFSET)
+			cs->sc_offset = 0;
+		else
+			cs->sc_offset = CCD_OFFSET;
+
+	}
 	for (ix = 0; ix < cs->sc_ndisks; ix++) {
 		ci = &cs->sc_cinfo[ix];
 
@@ -222,7 +239,7 @@
 		sectorsize = ci->ci_provider->sectorsize;
 		if (sectorsize > maxsecsize)
 			maxsecsize = sectorsize;
-		size = mediasize / DEV_BSIZE - CCD_OFFSET;
+		size = mediasize / DEV_BSIZE - cs->sc_offset;
 
 		/* Truncate to interleave boundary */
 
@@ -604,7 +621,7 @@
 	if (cbp == NULL)
 		return (ENOMEM);
 	cbp->bio_done = g_std_done;
-	cbp->bio_offset = dbtob(cbn + cboff + CCD_OFFSET);
+	cbp->bio_offset = dbtob(cbn + cboff + cs->sc_offset);
 	cbp->bio_data = addr;
 	if (cs->sc_ileave == 0)
               cbc = dbtob((off_t)(ci->ci_size - cbn));
@@ -739,6 +756,11 @@
 
 	sc->sc_unit = *unit;
 	sc->sc_ileave = *ileave;
+
+	if (gctl_get_param(req, "no_offset", NULL))
+		sc->sc_flags |= CCDF_NO_OFFSET;
+	if (gctl_get_param(req, "linux", NULL))
+		sc->sc_flags |= CCDF_LINUX;
 
 	if (gctl_get_param(req, "uniform", NULL))
 		sc->sc_flags |= CCDF_UNIFORM;
Index: sbin/ccdconfig/ccdconfig.8
===================================================================
RCS file: /lhome/CVS-FreeBSD/src/sbin/ccdconfig/ccdconfig.8,v
retrieving revision 1.35
diff -u -r1.35 ccdconfig.8
--- sbin/ccdconfig/ccdconfig.8	20 Aug 2005 09:10:31 -0000	1.35
+++ sbin/ccdconfig/ccdconfig.8	13 Apr 2006 19:47:45 -0000
@@ -104,6 +104,8 @@
 .Bd -literal -offset indent
 CCDF_UNIFORM	0x02		Use uniform interleave
 CCDF_MIRROR	0x04		Support mirroring
+CCDF_NO_OFFSET	0x08		Do not use an offset
+CCDF_LINUX	0x0A		Linux md(4) compatibility
 .Ed
 .Pp
 The format in the
@@ -127,6 +129,10 @@
 .Dq 4.2BSD
 as shown by
 .Xr disklabel 8 ) .
+.Pp
+If you want to use the Linux md(4) compatibility mode, please be sure
+to read the notes in
+.Xr ccd 4 .
 .Sh FILES
 .Bl -tag -width /etc/ccd.conf -compact
 .It Pa /etc/ccd.conf
@@ -157,6 +163,16 @@
 # ccdconfig ccd0 64 none /dev/da0s1 /dev/da1s1 /dev/da2s1 /dev/da3s1
 # ccdconfig ccd0 128 CCDF_MIRROR /dev/da4 /dev/da5 /dev/da6 /dev/da7
 # ccdconfig ccd0 128 CCDF_MIRROR /dev/da8s2 /dev/da9s3
+.Ed
+.Pp
+The following are matching commands in Linux and FreeBSD to create a
+raid-0 in Linux and read it from FreeBSD.
+.Bd -literal
+# Create a raid-0 on Linux:
+mdadm --create --chunk=32 --level=0 --raid-devices=2 /dev/md0 \\
+   /dev/hda1 /dev/hdb1
+# Make the raid-0 just created available on FreeBSD:
+ccdconfig -c /dev/ccd0 32 linux /dev/ad0s1 /dev/ad0s2
 .Ed
 .Pp
 When you create a new ccd disk you generally want to
Index: sbin/ccdconfig/ccdconfig.c
===================================================================
RCS file: /lhome/CVS-FreeBSD/src/sbin/ccdconfig/ccdconfig.c,v
retrieving revision 1.36
diff -u -r1.36 ccdconfig.c
--- sbin/ccdconfig/ccdconfig.c	5 Aug 2005 07:39:39 -0000	1.36
+++ sbin/ccdconfig/ccdconfig.c	13 Apr 2006 19:47:45 -0000
@@ -50,6 +50,8 @@
 
 #define CCDF_UNIFORM    0x02    /* use LCCD of sizes for uniform interleave */
 #define CCDF_MIRROR     0x04    /* use mirroring */
+#define CCDF_NO_OFFSET  0x08    /* do not leave space in front */
+#define CCDF_LINUX      0x10    /* use Linux compatibility mode */
 
 #include "pathnames.h"
 
@@ -65,6 +67,10 @@
 	{ "uniform",		CCDF_UNIFORM },
 	{ "CCDF_MIRROR",	CCDF_MIRROR },
 	{ "mirror",		CCDF_MIRROR },
+	{ "CCDF_NO_OFFSET",	CCDF_NO_OFFSET },
+	{ "no_offset",		CCDF_NO_OFFSET },
+	{ "CCDF_LINUX",		CCDF_LINUX },
+	{ "linux",		CCDF_LINUX },
 	{ "none",		0 },
 	{ NULL,			0 },
 };
@@ -245,6 +251,10 @@
 		gctl_ro_param(grq, "uniform", -1, "");
 	if (flags & CCDF_MIRROR)
 		gctl_ro_param(grq, "mirror", -1, "");
+	if (flags & CCDF_NO_OFFSET)
+		gctl_ro_param(grq, "no_offset", -1, "");
+	if (flags & CCDF_LINUX)
+		gctl_ro_param(grq, "linux", -1, "");
 	gctl_ro_param(grq, "nprovider", sizeof(argc), &argc);
 	for (i = 0; i < argc; i++) {
 		sprintf(buf1, "provider%d", i);
Index: share/man/man4/ccd.4
===================================================================
RCS file: /lhome/CVS-FreeBSD/src/share/man/man4/ccd.4,v
retrieving revision 1.30
diff -u -r1.30 ccd.4
--- share/man/man4/ccd.4	21 Jan 2005 08:36:37 -0000	1.30
+++ share/man/man4/ccd.4	13 Apr 2006 19:47:45 -0000
@@ -173,6 +173,34 @@
 .Nm
 partition without first backing up the partition, then replacing the disk,
 then restoring the partition.
+.Ss Linux compatibility
+The Linux compatibility mode does not try to read the label that Linux'
+md(4) driver leaves on the raw devices.  You will have to give the order
+of devices and the interleave factor on your own.  When in Linux
+compatibility mode, ccd will convert the interleave factor from Linux
+terminology.  That means you give the same interleave factor that you
+gave as chunk size in Linux.
+.Pp
+If you have a Linux md(4) device in "legacy" mode, do not use the
+CCD_LINUX flag in
+.Xr ccdconfig 8 .
+Use the CCD_NO_OFFSET flag instead.  In that case you have to convert
+the interleave factor on your own, usually it is Linux' chunk size
+multiplied by two.
+.Pp
+Using a Linux raid this way is potentially dangerous and can destroy
+the data in there.  Since FreeBSD does not read the label used by
+Linux, changes in Linux might invalidate the compatibility layer.
+.Pp
+However, using this is reasonably safe if you test the compatibility
+before mounting a raid read-write for the first time.  Just using
+ccdconfig without mounting does not write anything to the Linux raid.
+Then you do a fsck.ex2fs on the ccd device using the -n flag.  You can
+mount the filesystem readonly to check files in there.  If all this
+works, it is unlikely that there is a problem with ccd.  Keep in mind
+that even when the Linux compatibility mode in ccd is working
+correctly, bugs in FreeBSD's ex2fs implementation would still destroy
+your data.
 .Sh WARNINGS
 If just one (or more) of the disks in a
 .Nm
