NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/53506: Easy trigger of "panic: biodone2 already" on NetBSD 8.0 Xen domU



The following reply was made to PR port-xen/53506; it has been noted by GNATS.

From: Emmanuel Dreyfus <manu%netbsd.org@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: kern/53506: Easy trigger of "panic: biodone2 already" on NetBSD
 8.0 Xen domU
Date: Mon, 20 Aug 2018 01:38:59 +0000

 --/04w6evG8XlLl3ft
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 The attached patch clears the struct xbd_req content between usage, 
 while there adds a few sanity checks. At mine it is enough to 
 prevent any panic on biodone2 already.
 
 If it looks good enough, I think we should pull it up to netbsd-8 so
 that backups are possible again. The code can be more heavily 
 reworked on -current afterwards.
 
 --  
 Emmanuel Dreyfus
 manu%netbsd.org@localhost
 
 --/04w6evG8XlLl3ft
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=patch-biodone2already
 
 --- ./sys/arch/xen/xen/xbd_xenbus.c.orig
 +++ ./sys/arch/xen/xen/xbd_xenbus.c
 @@ -222,8 +222,21 @@
  	.d_close = xbdclose,
  	.d_diskstart = xbd_diskstart,
  };
  
 +static inline void
 +xbd_xbdreq_clear(struct xbd_xenbus_softc *sc, struct xbd_req *xbdreq)
 +{       
 +	int i = xbdreq - sc->sc_reqs;
 +
 +	KASSERT(xbdreq->req_id == i);
 +	memset(xbdreq, 0, sizeof(*xbdreq));
 +	xbdreq->req_id = i;
 +
 +	return;
 +}
 +
 +
  static int
  xbd_xenbus_match(device_t parent, cfdata_t match, void *aux)
  {
  	struct xenbusdev_attach_args *xa = aux;
 @@ -652,8 +665,9 @@
  	for (i = sc->sc_ring.rsp_cons; i != resp_prod; i++) {
  		blkif_response_t *rep = RING_GET_RESPONSE(&sc->sc_ring, i);
  		struct xbd_req *xbdreq = &sc->sc_reqs[rep->id];
  		bp = xbdreq->req_bp;
 +		KASSERT(bp != NULL);
  		DPRINTF(("xbd_handler(%p): b_bcount = %ld\n",
  		    xbdreq->req_bp, (long)bp->b_bcount));
  		if (rep->operation == BLKIF_OP_FLUSH_DISKCACHE) {
  			xbdreq->req_sync.s_error = rep->status;
 @@ -693,8 +707,9 @@
  			xbd_unmap_align(xbdreq);
  
  		dk_done(&sc->sc_dksc, bp);
  
 +		xbdreq->req_bp = NULL; /* Do not reuse */
  		SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next);
  	}
  done:
  	xen_rmb();
 @@ -854,8 +869,9 @@
  		if (__predict_false(xbdreq == NULL)) {
  			DPRINTF(("xbdioctl: no req\n"));
  			error = ENOMEM;
  		} else {
 +			xbd_xbdreq_clear(sc, xbdreq);
  			SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next);
  			req = RING_GET_REQUEST(&sc->sc_ring,
  			    sc->sc_ring.req_prod_pvt);
  			req->id = xbdreq->req_id;
 @@ -952,8 +968,9 @@
  		error = EAGAIN;
  		goto out;
  	}
  
 +	xbd_xbdreq_clear(sc, xbdreq);
  	xbdreq->req_bp = bp;
  	xbdreq->req_data = bp->b_data;
  	if ((vaddr_t)bp->b_data & (XEN_BSIZE - 1)) {
  		if (__predict_false(xbd_map_align(xbdreq) != 0)) {
 
 --/04w6evG8XlLl3ft--
 


Home | Main Index | Thread Index | Old Index