Module Name:    src
Committed By:   bsh
Date:           Tue Jul  6 17:56:15 UTC 2010

Modified Files:
        src/sys/dev/ata: ld_ataraid.c

Log Message:
fix LOCKDEBUG panic at ataraid(4).
the patch was provided by Juan RP in response to PR kern 38273.
(http://mail-index.netbsd.org/tech-kern/2008/09/17/msg002734.html)


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/dev/ata/ld_ataraid.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ata/ld_ataraid.c
diff -u src/sys/dev/ata/ld_ataraid.c:1.35 src/sys/dev/ata/ld_ataraid.c:1.36
--- src/sys/dev/ata/ld_ataraid.c:1.35	Tue May 12 14:16:53 2009
+++ src/sys/dev/ata/ld_ataraid.c	Tue Jul  6 17:56:14 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ld_ataraid.c,v 1.35 2009/05/12 14:16:53 cegger Exp $	*/
+/*	$NetBSD: ld_ataraid.c,v 1.36 2010/07/06 17:56:14 bsh Exp $	*/
 
 /*
  * Copyright (c) 2003 Wasabi Systems, Inc.
@@ -47,7 +47,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.35 2009/05/12 14:16:53 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.36 2010/07/06 17:56:14 bsh Exp $");
 
 #include "bio.h"
 #include "rnd.h"
@@ -90,6 +90,12 @@
 	struct vnode *sc_vnodes[ATA_RAID_MAX_DISKS];
 
 	void	(*sc_iodone)(struct buf *);
+
+       pool_cache_t sc_cbufpool;
+
+       SIMPLEQ_HEAD(, cbuf) sc_cbufq;
+
+       void    *sc_sih_cookie;
 };
 
 static int	ld_ataraid_match(device_t, cfdata_t, void *);
@@ -97,6 +103,10 @@
 
 static int	ld_ataraid_dump(struct ld_softc *, void *, int, int);
 
+static int     cbufpool_ctor(void *, void *, int);
+static void    cbufpool_dtor(void *, void *);
+
+static void    ld_ataraid_start_vstrategy(void *);
 static int	ld_ataraid_start_span(struct ld_softc *, struct buf *);
 
 static int	ld_ataraid_start_raid0(struct ld_softc *, struct buf *);
@@ -113,9 +123,6 @@
 CFATTACH_DECL_NEW(ld_ataraid, sizeof(struct ld_ataraid_softc),
     ld_ataraid_match, ld_ataraid_attach, NULL, NULL);
 
-static int ld_ataraid_initialized;
-static struct pool ld_ataraid_cbufpl;
-
 struct cbuf {
 	struct buf	cb_buf;		/* new I/O buf */
 	struct buf	*cb_obp;	/* ptr. to original I/O buf */
@@ -127,8 +134,8 @@
 #define	CBUF_IODONE	0x00000001	/* I/O is already successfully done */
 };
 
-#define	CBUF_GET()	pool_get(&ld_ataraid_cbufpl, PR_NOWAIT);
-#define	CBUF_PUT(cbp)	pool_put(&ld_ataraid_cbufpl, (cbp))
+#define        CBUF_GET()      pool_cache_get(sc->sc_cbufpool, PR_NOWAIT);
+#define        CBUF_PUT(cbp)   pool_cache_put(sc->sc_cbufpool, (cbp))
 
 static int
 ld_ataraid_match(device_t parent, cfdata_t match, void *aux)
@@ -151,11 +158,10 @@
 
 	ld->sc_dv = self;
 
-	if (ld_ataraid_initialized == 0) {
-		ld_ataraid_initialized = 1;
-		pool_init(&ld_ataraid_cbufpl, sizeof(struct cbuf), 0,
-		    0, 0, "ldcbuf", NULL, IPL_BIO);
-	}
+       sc->sc_cbufpool = pool_cache_init(sizeof(struct cbuf), 0,
+           0, 0, "ldcbuf", NULL, IPL_BIO, cbufpool_ctor, cbufpool_dtor, sc);
+       sc->sc_sih_cookie = softint_establish(SOFTINT_BIO,
+           ld_ataraid_start_vstrategy, sc);
 
 	sc->sc_aai = aai;	/* this data persists */
 
@@ -246,9 +252,33 @@
 		panic("%s: bioctl registration failed\n",
 		    device_xname(ld->sc_dv));
 #endif
+       SIMPLEQ_INIT(&sc->sc_cbufq);
 	ldattach(ld);
 }
 
+static int
+cbufpool_ctor(void *arg, void *obj, int flags)
+{
+       struct ld_ataraid_softc *sc = arg;
+       struct ld_softc *ld = &sc->sc_ld;
+       struct cbuf *cbp = obj;
+
+       /* We release/reacquire the spinlock before calling buf_init() */
+       mutex_exit(&ld->sc_mutex);
+       buf_init(&cbp->cb_buf);
+       mutex_enter(&ld->sc_mutex);
+
+       return 0;
+}
+
+static void
+cbufpool_dtor(void *arg, void *obj)
+{
+       struct cbuf *cbp = obj;
+
+       buf_destroy(&cbp->cb_buf);
+}
+
 static struct cbuf *
 ld_ataraid_make_cbuf(struct ld_ataraid_softc *sc, struct buf *bp,
     u_int comp, daddr_t bn, void *addr, long bcount)
@@ -257,8 +287,7 @@
 
 	cbp = CBUF_GET();
 	if (cbp == NULL)
-		return (NULL);
-	buf_init(&cbp->cb_buf);
+               return NULL;
 	cbp->cb_buf.b_flags = bp->b_flags;
 	cbp->cb_buf.b_oflags = bp->b_oflags;
 	cbp->cb_buf.b_cflags = bp->b_cflags;
@@ -277,7 +306,24 @@
 	cbp->cb_other = NULL;
 	cbp->cb_flags = 0;
 
-	return (cbp);
+       return cbp;
+}
+
+static void
+ld_ataraid_start_vstrategy(void *arg)
+{
+       struct ld_ataraid_softc *sc = arg;
+       struct cbuf *cbp;
+
+       while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q);
+               if ((cbp->cb_buf.b_flags & B_READ) == 0) {
+                       mutex_enter(&cbp->cb_buf.b_vp->v_interlock);
+                       cbp->cb_buf.b_vp->v_numoutput++;
+                       mutex_exit(&cbp->cb_buf.b_vp->v_interlock);
+               }
+               VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf);
+       }
 }
 
 static int
@@ -286,7 +332,6 @@
 	struct ld_ataraid_softc *sc = (void *) ld;
 	struct ataraid_array_info *aai = sc->sc_aai;
 	struct ataraid_disk_info *adi;
-	SIMPLEQ_HEAD(, cbuf) cbufq;
 	struct cbuf *cbp;
 	char *addr;
 	daddr_t bn;
@@ -294,7 +339,6 @@
 	u_int comp;
 
 	/* Allocate component buffers. */
-	SIMPLEQ_INIT(&cbufq);
 	addr = bp->b_data;
 
 	/* Find the first component. */
@@ -316,12 +360,11 @@
 		cbp = ld_ataraid_make_cbuf(sc, bp, comp, bn, addr, rcount);
 		if (cbp == NULL) {
 			/* Free the already allocated component buffers. */
-			while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-				SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-				buf_destroy(&cbp->cb_buf);
+                       while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) {
+                               SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q);
 				CBUF_PUT(cbp);
 			}
-			return (EAGAIN);
+                       return EAGAIN;
 		}
 
 		/*
@@ -331,31 +374,22 @@
 		adi = &aai->aai_disks[++comp];
 		bn = 0;
 
-		SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
+               SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq, cbp, cb_q);
 		addr += rcount;
 	}
 
 	/* Now fire off the requests. */
-	while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-		SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-		if ((cbp->cb_buf.b_flags & B_READ) == 0) {
-			mutex_enter(&cbp->cb_buf.b_vp->v_interlock);
-			cbp->cb_buf.b_vp->v_numoutput++;
-			mutex_exit(&cbp->cb_buf.b_vp->v_interlock);
-		}
-		VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf);
-	}
+       softint_schedule(sc->sc_sih_cookie);
 
-	return (0);
+       return 0;
 }
 
 static int
 ld_ataraid_start_raid0(struct ld_softc *ld, struct buf *bp)
 {
-	struct ld_ataraid_softc *sc = (void *) ld;
+       struct ld_ataraid_softc *sc = (void *)ld;
 	struct ataraid_array_info *aai = sc->sc_aai;
 	struct ataraid_disk_info *adi;
-	SIMPLEQ_HEAD(, cbuf) cbufq;
 	struct cbuf *cbp, *other_cbp;
 	char *addr;
 	daddr_t bn, cbn, tbn, off;
@@ -363,10 +397,9 @@
 	u_int comp;
 	const int read = bp->b_flags & B_READ;
 	const int mirror = aai->aai_level & AAI_L_RAID1;
-	int error;
+       int error = 0;
 
 	/* Allocate component buffers. */
-	SIMPLEQ_INIT(&cbufq);
 	addr = bp->b_data;
 	bn = bp->b_rawblkno;
 
@@ -417,14 +450,13 @@
 			error = EAGAIN;
 free_and_exit:
 			/* Free the already allocated component buffers. */
-			while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-				SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-				buf_destroy(&cbp->cb_buf);
+                       while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) {
+                               SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q);
 				CBUF_PUT(cbp);
 			}
-			return (error);
+                       return error;
 		}
-		SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
+               SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq, cbp, cb_q);
 		if (mirror && !read && comp < aai->aai_width) {
 			comp += aai->aai_width;
 			adi = &aai->aai_disks[comp];
@@ -433,7 +465,8 @@
 				    comp, cbn, addr, rcount);
 				if (other_cbp == NULL)
 					goto resource_shortage;
-				SIMPLEQ_INSERT_TAIL(&cbufq, other_cbp, cb_q);
+                               SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq,
+                                   other_cbp, cb_q);
 				other_cbp->cb_other = cbp;
 				cbp->cb_other = other_cbp;
 			}
@@ -443,17 +476,9 @@
 	}
 
 	/* Now fire off the requests. */
-	while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-		SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-		if ((cbp->cb_buf.b_flags & B_READ) == 0) {
-			mutex_enter(&cbp->cb_buf.b_vp->v_interlock);
-			cbp->cb_buf.b_vp->v_numoutput++;
-			mutex_exit(&cbp->cb_buf.b_vp->v_interlock);
-		}
-		VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf);
-	}
+       softint_schedule(sc->sc_sih_cookie);
 
-	return (0);
+       return error;
 }
 
 /*
@@ -530,7 +555,6 @@
 			other_cbp->cb_flags |= CBUF_IODONE;
 	}
 	count = cbp->cb_buf.b_bcount;
-	buf_destroy(&cbp->cb_buf);
 	CBUF_PUT(cbp);
 
 	if (other_cbp != NULL)

Reply via email to