ccd on NATA problem - ata0: FAILURE - oversized DMA transfer attempt 73728 > 65536

Matthew Dillon dillon at apollo.backplane.com
Mon Jul 9 10:51:57 PDT 2007


:IIUC, in old-ATA, ad_strategy took care of transfer sizes larger than
:the maximum I/O size of the device, but not in NATA (I guess GEOM layer
:is handling it, right?).  Adjusting si_iosize_max (initially faked to
:be 131072 when attached) in ccdinit() seems to work around this problem.
:
:Cheers.

    There's even an XXX comment next to that assignment.  At the time
    that assignment is made the CCD hasn't loaded its components yet
    so we do not know what the actual limitations are.

    CCD has an iterator in ccdstart() to deal with components.  I think
    what we need to do is to add some logic to ccdbuffer() to incorporate
    the limits of the lower level device. 

    So, please try this patch.  I've included a kprintf() so we can get
    positive confirmation that it actually does what it is supposed to.

    The advantage of this patch is that it does not artificially limit
    the max iosize for the CCD request itself.  e.g. if a person happens
    to configure an interleave of 64K across two disks CCD which are
    each limited to 64K I/O's, CCD will still process a 128K I/O in
    parallel.

    Please note this patch is almost completely untested.

						-Matt


Index: sys/ccdvar.h
===================================================================
RCS file: /cvs/src/sys/sys/ccdvar.h,v
retrieving revision 1.6
diff -u -p -r1.6 ccdvar.h
--- sys/ccdvar.h	17 May 2007 03:20:11 -0000	1.6
+++ sys/ccdvar.h	9 Jul 2007 17:29:55 -0000
@@ -206,6 +206,7 @@ 	int		 sc_flags;		/* flags */
 	int		 sc_cflags;		/* configuration flags */
 	u_int64_t	 sc_size;		/* size of ccd in sectors */
 	int		 sc_ileave;		/* interleave */
+	int		 sc_maxiosize;		/* maximum I/O size */
 	u_int		 sc_nccdisks;		/* number of components */
 #define	CCD_MAXNDISKS	 65536
 	struct ccdcinfo	 *sc_cinfo;		/* component info */
Index: dev/disk/ccd/ccd.c
===================================================================
RCS file: /cvs/src/sys/dev/disk/ccd/ccd.c,v
retrieving revision 1.48
diff -u -p -r1.48 ccd.c
--- dev/disk/ccd/ccd.c	19 Jun 2007 19:09:46 -0000	1.48
+++ dev/disk/ccd/ccd.c	9 Jul 2007 17:42:52 -0000
@@ -398,6 +398,7 @@ 
 	/* Allocate space for the component info. */
 	cs->sc_cinfo = kmalloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
 				M_DEVBUF, M_WAITOK);
+	cs->sc_maxiosize = MAXPHYS;
 
 	/*
 	 * Verify that each component piece exists and record
@@ -427,6 +428,10 @@ 		ci->ci_path = kmalloc(ci->ci_pathlen, 
 		bcopy(tmppath, ci->ci_path, ci->ci_pathlen);
 
 		ci->ci_dev = vn_todev(vp);
+		if (ci->ci_dev->si_iosize_max &&
+		    cs->sc_maxiosize > ci->ci_dev->si_iosize_max) {
+			cs->sc_maxiosize = ci->ci_dev->si_iosize_max;
+		}
 
 		/*
 		 * Get partition information for the component.
@@ -489,6 +494,8 @@ 		ci->ci_skip = skip;
 		ci->ci_size = size;
 		cs->sc_size += size;
 	}
+	kprintf("ccd%d: max component iosize is %d\n",
+		cs->sc_unit, cs->sc_maxiosize);
 
 	/*
 	 * Don't allow the interleave to be smaller than
@@ -1048,9 +1055,11 @@ 	cbp->cb_buf.b_flags |= bio->bio_buf->b_
 	cbp->cb_buf.b_data = addr;
 	cbp->cb_vp = ci->ci_vp;
 	if (cs->sc_ileave == 0)
-              cbc = dbtob((off_t)(ci->ci_size - cbn));
+		cbc = dbtob((off_t)(ci->ci_size - cbn));
 	else
-              cbc = dbtob((off_t)(cs->sc_ileave - cboff));
+		cbc = dbtob((off_t)(cs->sc_ileave - cboff));
+	if (cbc > cs->sc_maxiosize)
+		cbc = cs->sc_maxiosize;
 	cbp->cb_buf.b_bcount = (cbc < bcount) ? cbc : bcount;
  	cbp->cb_buf.b_bufsize = cbp->cb_buf.b_bcount;
 
@@ -1090,6 +1099,8 @@ 		if (cs->sc_ileave == 0)
 		      cbc = dbtob((off_t)(ci->ci_size - cbn));
 		else
 		      cbc = dbtob((off_t)(cs->sc_ileave - cboff));
+		if (cbc > cs->sc_maxiosize)
+			cbc = cs->sc_maxiosize;
 		cbp->cb_buf.b_bcount = (cbc < bcount) ? cbc : bcount;
 		cbp->cb_buf.b_bufsize = cbp->cb_buf.b_bcount;
 





More information about the Bugs mailing list