tech-kern archive

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

Re: biodone() and splbio ?



On Tue, Jan 19, 2010 at 10:52:49PM +0100, Manuel Bouyer wrote:
> On Tue, Jan 19, 2010 at 10:43:04PM +0100, Manuel Bouyer wrote:
> > [...]
> > If not, dk.c needs to be fixed to raise to splbio() in its done routine.
> > raidcframe already does it. I suspect ccdiodone() and vndiodone()
> > need it too.
> 
> Maybe not; it seems ccd is MP-safe.
> For vnd, the lack of appropriate spl call here can corrupt sc_active count,
> but it seems it can't corrupt the buffer queue.


Here is my proposed patch for this issue. dk(4) tested, and this most probably
fixed the issue (uptime > 1d, would crash within a few hours before),
cgd(4) and vnd(4) compile-tested only but I don't expect problems here.

Does anyone see a problem with this ?

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: cgd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/cgd.c,v
retrieving revision 1.53.4.2
diff -u -r1.53.4.2 cgd.c
--- cgd.c       4 Apr 2009 17:18:53 -0000       1.53.4.2
+++ cgd.c       21 Jan 2010 16:45:39 -0000
@@ -344,13 +344,13 @@
        return 0;
 }
 
-/* expected to be called at splbio() */
 static void
 cgdiodone(struct buf *nbp)
 {
        struct  buf *obp = nbp->b_private;
        struct  cgd_softc *cs = getcgd_softc(obp->b_dev);
        struct  dk_softc *dksc = &cs->sc_dksc;
+       int s;
 
        KDASSERT(cs);
 
@@ -385,10 +385,12 @@
        obp->b_resid = 0;
        if (obp->b_error != 0)
                obp->b_resid = obp->b_bcount;
+       s = splbio();
        disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
            (obp->b_flags & B_READ));
        biodone(obp);
        dk_iodone(di, dksc);
+       splx(s);
 }
 
 /* XXX: we should probably put these into dksubr.c, mostly */
Index: vnd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/vnd.c,v
retrieving revision 1.187.4.3
diff -u -r1.187.4.3 vnd.c
--- vnd.c       4 Apr 2009 17:20:00 -0000       1.187.4.3
+++ vnd.c       21 Jan 2010 16:45:39 -0000
@@ -862,6 +862,7 @@
        struct vndxfer *vnx = VND_BUFTOXFER(bp);
        struct vnd_softc *vnd = vnx->vx_vnd;
        struct buf *obp = bp->b_private;
+       int s = splbio();
 
        KASSERT(&vnx->vx_buf == bp);
        KASSERT(vnd->sc_active > 0);
@@ -877,6 +878,7 @@
        if (vnd->sc_active == 0) {
                wakeup(&vnd->sc_tab);
        }
+       splx(s);
        obp->b_error = bp->b_error;
        obp->b_resid = bp->b_resid;
        buf_destroy(bp);
Index: dkwedge/dk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dkwedge/dk.c,v
retrieving revision 1.42
diff -u -r1.42 dk.c
--- dkwedge/dk.c        17 Jun 2008 14:53:10 -0000      1.42
+++ dkwedge/dk.c        21 Jan 2010 16:45:39 -0000
@@ -1100,7 +1100,6 @@
  * dkiodone:
  *
  *     I/O to a wedge has completed; alert the top half.
- *     NOTE: Must be called at splbio()!
  */
 static void
 dkiodone(struct buf *bp)
@@ -1108,6 +1107,8 @@
        struct buf *obp = bp->b_private;
        struct dkwedge_softc *sc = dkwedge_lookup(obp->b_dev);
 
+       int s = splbio();
+
        if (bp->b_error != 0)
                obp->b_error = bp->b_error;
        obp->b_resid = bp->b_resid;
@@ -1125,6 +1126,7 @@
 
        /* Kick the queue in case there is more work we can do. */
        dkstart(sc);
+       splx(s);
 }
 
 /*


Home | Main Index | Thread Index | Old Index