Module Name:    src
Committed By:   bouyer
Date:           Mon Sep 21 21:59:30 UTC 2009

Modified Files:
        src/sys/arch/xen/xen: xbd_xenbus.c

Log Message:
Allow a xbd to be detached from the domU (e.g. at shutdown). Patch tested
and adjusted by David Young, discussed on port-xen@ early august.


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/xen/xen/xbd_xenbus.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/arch/xen/xen/xbd_xenbus.c
diff -u src/sys/arch/xen/xen/xbd_xenbus.c:1.41 src/sys/arch/xen/xen/xbd_xenbus.c:1.42
--- src/sys/arch/xen/xen/xbd_xenbus.c:1.41	Wed Jul 29 12:02:10 2009
+++ src/sys/arch/xen/xen/xbd_xenbus.c	Mon Sep 21 21:59:30 2009
@@ -1,4 +1,4 @@
-/*      $NetBSD: xbd_xenbus.c,v 1.41 2009/07/29 12:02:10 cegger Exp $      */
+/*      $NetBSD: xbd_xenbus.c,v 1.42 2009/09/21 21:59:30 bouyer Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.41 2009/07/29 12:02:10 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.42 2009/09/21 21:59:30 bouyer Exp $");
 
 #include "opt_xen.h"
 #include "rnd.h"
@@ -110,6 +110,9 @@
 #define BLKIF_STATE_CONNECTED    1
 #define BLKIF_STATE_SUSPENDED    2
 	int sc_shutdown;
+#define BLKIF_SHUTDOWN_RUN    0 /* no shutdown */
+#define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */
+#define BLKIF_SHUTDOWN_LOCAL  2 /* locally-initiated shutdown in progress */
 
 	uint64_t sc_sectors; /* number of sectors for this device */
 	u_long sc_secsize; /* sector size */
@@ -140,8 +143,9 @@
 static int  xbd_map_align(struct xbd_req *);
 static void xbd_unmap_align(struct xbd_req *);
 
-CFATTACH_DECL_NEW(xbd, sizeof(struct xbd_xenbus_softc),
-   xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL);
+CFATTACH_DECL3_NEW(xbd, sizeof(struct xbd_xenbus_softc),
+   xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL, NULL, NULL,
+   DVF_DETACH_SHUTDOWN);
 
 dev_type_open(xbdopen);
 dev_type_close(xbdclose);
@@ -249,7 +253,7 @@
 	}
 
 	sc->sc_backend_status = BLKIF_STATE_DISCONNECTED;
-	sc->sc_shutdown = 1;
+	sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
 	/* initialise shared structures and tell backend that we are ready */
 	xbd_xenbus_resume(sc);
 
@@ -263,16 +267,31 @@
 xbd_xenbus_detach(device_t dev, int flags)
 {
 	struct xbd_xenbus_softc *sc = device_private(dev);
-	int s, bmaj, cmaj, i, mn;
+	int bmaj, cmaj, i, mn, rc, s;
+
+	rc = disk_begindetach(&sc->sc_dksc.sc_dkdev, NULL, dev, flags);
+	if (rc != 0)
+		return rc;
+
 	s = splbio();
 	DPRINTF(("%s: xbd_detach\n", device_xname(dev)));
-	if (sc->sc_shutdown == 0) {
-		sc->sc_shutdown = 1;
+	if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) {
+		sc->sc_shutdown = BLKIF_SHUTDOWN_LOCAL;
 		/* wait for requests to complete */
 		while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
 		    sc->sc_dksc.sc_dkdev.dk_stats->io_busy > 0)
 			tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
+		xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosing);
 	}
+	if ((flags & DETACH_FORCE) == 0) {
+		/* xbd_xenbus_detach already in progress */
+		wakeup(xbd_xenbus_detach);
+		splx(s);
+		return EALREADY;
+	}
+	while (xenbus_read_driver_state(sc->sc_xbusd->xbusd_otherend)
+	    != XenbusStateClosed)
+		tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach2", hz/2);
 	splx(s);
 
 	/* locate the major number */
@@ -414,12 +433,12 @@
 		break;
 	case XenbusStateClosing:
 		s = splbio();
-		sc->sc_shutdown = 1;
+		if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN)
+			sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
 		/* wait for requests to complete */
 		while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
 		    sc->sc_dksc.sc_dkdev.dk_stats->io_busy > 0)
-			tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach",
-			    hz/2);
+			tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
 		splx(s);
 		xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed);
 		break;
@@ -434,7 +453,7 @@
 			return;
 
 		xbd_connect(sc);
-		sc->sc_shutdown = 0;
+		sc->sc_shutdown = BLKIF_SHUTDOWN_RUN;
 		hypervisor_enable_event(sc->sc_evtchn);
 
 		sc->sc_xbdsize =
@@ -635,7 +654,7 @@
 	DPRINTF(("xbdstrategy(%p): b_bcount = %ld\n", bp,
 	    (long)bp->b_bcount));
 
-	if (sc == NULL || sc->sc_shutdown) {
+	if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
 		bp->b_error = EIO;
 		biodone(bp);
 		return;
@@ -659,7 +678,7 @@
 	DPRINTF(("xbdsize(%d)\n", dev));
 
 	sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
-	if (sc == NULL || sc->sc_shutdown)
+	if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN)
 		return -1;
 	return dk_size(sc->sc_di, &sc->sc_dksc, dev);
 }
@@ -750,7 +769,7 @@
 	DPRINTF(("xbdstart(%p): b_bcount = %ld\n", bp, (long)bp->b_bcount));
 
 	sc = device_lookup_private(&xbd_cd, DISKUNIT(bp->b_dev));
-	if (sc == NULL || sc->sc_shutdown) {
+	if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
 		bp->b_error = EIO;
 		goto err;
 	}

Reply via email to