Subject: Re: kern/3765: ccd mirror panic on sun4m
To: None <gnats-bugs@gnats.netbsd.org, fair@digital.clock.org>
From: Paul Kranenburg <pk@cs.few.eur.nl>
List: netbsd-bugs
Date: 06/20/1997 16:21:46
> 	an attempt to use a mirror ccd on NetBSD-current on sun4m
> 	causes the following:
> 
> 		pmap_extract: invalid pte of type 0
> 		panic: dvma_mapin: null page frame


I think the twin transactions started by ccd on mirrored configurations
should wait for each other to complete. Otherwise, the original buffer
may be dismantled while the "mirrored" I/O is still in progress.

Can you give this patch a try, please?

-------------------------------------------------------------------------------

*** /usr/src/sys/dev/ccd.c	Fri Jun 20 16:08:02 1997
--- ccd.c	Fri Jun 20 16:09:02 1997
***************
*** 132,142 ****
--- 132,144 ----
  	int		cb_unit;	/* target unit */
  	int		cb_comp;	/* target component */
  	int		cb_flags;	/* misc. flags */
+ 	struct ccdbuf	*cb_other;	/* ptr to twin mirror buffer */
  	LIST_ENTRY(ccdbuf) cb_list;	/* entry on freelist */
  };
  
  /* cb_flags */
  #define CBF_MIRROR	0x01		/* we're for a mirror component */
+ #define CBF_WAITOTHER	0x02		/* wait for mirror component to complete */
  
  /*
   * Number of freelist buffers per component.  Overridable in kernel
***************
*** 880,885 ****
--- 882,888 ----
  	cbp->cb_obp = bp;
  	cbp->cb_unit = cs->sc_unit;
  	cbp->cb_comp = ccdisk;
+ 	cbp->cb_other = NULL;
  
  	/* First buffer is dealt with. */
  	cbpp[0] = cbp;
***************
*** 903,908 ****
--- 906,915 ----
  		cbp->cb_buf.b_dev = ci2->ci_dev;	/* XXX */
  		cbp->cb_buf.b_vp = ci2->ci_vp;
  		cbp->cb_comp = ci2 - cs->sc_cinfo;
+ 		cbp->cb_other = cbpp[0];
+ 		cbpp[0]->cb_other = cbp;
+ 		cbpp[0]->cb_flags |= CBF_WAITOTHER;
+ 		cbp->cb_flags |= CBF_WAITOTHER;
  		cbpp[1] = cbp;
  	}
  }
***************
*** 974,979 ****
--- 981,992 ----
  	}
  	count = cbp->cb_buf.b_bcount;
  	cbflags = cbp->cb_flags;
+ 
+ 	if ((cbflags & CBF_WAITOTHER) != 0) {
+ 		if (cbp->cb_other == NULL)
+ 			panic("ccdiodone: other == NULL");
+ 		cbp->cb_other->cb_flags &= ~CBF_WAITOTHER;
+ 	}
  	CCDPUTBUF(cs, cbp);
  
  	/*
***************
*** 986,994 ****
  		bp->b_resid -= count;
  		if (bp->b_resid < 0)
  			panic("ccdiodone: count");
! 		if (bp->b_resid == 0)
  			ccdintr(&ccd_softc[unit], bp);
! 	}
  	splx(s);
  }
  
--- 999,1009 ----
  		bp->b_resid -= count;
  		if (bp->b_resid < 0)
  			panic("ccdiodone: count");
! 		if (bp->b_resid == 0 && (cbflags & CBF_WAITOTHER) == 0)
  			ccdintr(&ccd_softc[unit], bp);
! 	} else if (bp->b_resid == 0 && (cbflags & CBF_WAITOTHER) == 0)
! 		ccdintr(&ccd_softc[unit], bp);
! 
  	splx(s);
  }