Port-xen archive

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

port-xen/33110: map_align() in xbd.c may sleep



[To, hopefully, summarize my PR:]

On the -3 branch, I can get a panic in xbd pretty reliably (on at
least one test host) when map_align()'s memory allocation fails and
tries to sleep; it's in interrupt context, of course, so it can't.

It looks like this was fixed in -current, but that's tangled up in a
bunch of major infrastructure changes, and so pulling it up would be
hard or impossible.

So, I've attempted to get xbdstart() as it exists in -3 to fail
gracefully and put off the I/O for later (patch attached, and will be
added to the PR), but I may well have gotten it wrong.

-- 
(let ((C call-with-current-continuation)) (apply (lambda (x y) (x y)) (map
((lambda (r) ((C C) (lambda (s) (r (lambda l (apply (s s) l))))))  (lambda
(f) (lambda (l) (if (null? l) C (lambda (k) (display (car l)) ((f (cdr l))
(C k)))))))    '((#\J #\d #\D #\v #\s) (#\e #\space #\a #\i #\newline)))))
Index: arch/xen/xen/xbd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/xbd.c,v
retrieving revision 1.14.2.5
diff -u -p -r1.14.2.5 xbd.c
--- arch/xen/xen/xbd.c  28 Apr 2005 10:28:42 -0000      1.14.2.5
+++ arch/xen/xen/xbd.c  20 Mar 2006 23:22:22 -0000
@@ -1140,7 +1140,7 @@ xbdsize(dev_t dev)
        return dk_size(xs->sc_di, &xs->sc_dksc, dev);
 }
 
-static void
+static int
 map_align(struct xbdreq *xr)
 {
        int s;
@@ -1148,8 +1148,10 @@ map_align(struct xbdreq *xr)
        s = splvm();
        xr->xr_aligned = uvm_km_kmemalloc1(kmem_map, NULL,
            xr->xr_bqueue, XEN_BSIZE, UVM_UNKNOWN_OFFSET,
-           0/*  UVM_KMF_NOWAIT */);
+           UVM_KMF_NOWAIT);
        splx(s);
+       if (xr->xr_aligned == 0)
+               return 0;
        DPRINTF(XBDB_IO, ("map_align(%p): bp %p addr %p align 0x%08lx "
            "size 0x%04lx\n", xr, xr->xr_bp, xr->xr_bp->b_data,
            xr->xr_aligned, xr->xr_bqueue));
@@ -1157,6 +1159,7 @@ map_align(struct xbdreq *xr)
        if ((xr->xr_bp->b_flags & B_READ) == 0)
                memcpy((void *)xr->xr_aligned, xr->xr_bp->b_data,
                    xr->xr_bqueue);
+       return 1;
 }
 
 static void
@@ -1361,7 +1364,13 @@ xbdstart(struct dk_softc *dksc, struct b
        pxr->xr_sc = xs;
 
        if (pxr->xr_data & (XEN_BSIZE - 1))
-               map_align(pxr);
+               if (!map_align(pxr)) { /* No memory; try later. */
+                       DPRINTF(XBDB_IO, ("xbdstart: map_align failed\n"));
+                       ret = -1;
+                       disk_unbusy(&dksc->sc_dkdev, 0, bp->b_flags & B_READ);
+                       PUT_XBDREQ(pxr);
+                       goto out;
+               }
 
        fill_ring(pxr);
 


Home | Main Index | Thread Index | Old Index