Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Jun 2013 04:51:32 +0000 (UTC)
From:      "Justin T. Gibbs" <gibbs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251772 - head/sys/dev/xen/blkfront
Message-ID:  <201306150451.r5F4pWJm023492@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gibbs
Date: Sat Jun 15 04:51:31 2013
New Revision: 251772
URL: http://svnweb.freebsd.org/changeset/base/251772

Log:
  Properly track the different reasons new I/O is temporarily disabled, and
  only re-enable I/O when all reasons have cleared.
  
  sys/dev/xen/blkfront/block.h:
  	In the block front driver softc, replace the boolean
  	XBDF_FROZEN flag with a count of commands and driver global
  	issues that freeze the I/O queue.  So long xbd_qfrozen_cnt
  	is non-zero, I/O is halted.
  
  	Add flags to xbd_flags for tracking grant table entry and
  	free command resource shortages.  Each of these classes can
  	increment xbd_qfrozen_cnt at most once.
  
  	Add a command flag (XBDCF_ASYNC_MAPPING) that is set whenever
  	the initial mapping attempt of a command fails with EINPROGRESS.
  
  sys/dev/xen/blkfront/blkfront.c:
  	In xbd_queue_cb(), use new XBDCF_ASYNC_MAPPING flag to definitively
  	know if an async bus dmamap load has occurred.
  
  	Add xbd_freeze() and xbd_thaw() helper methods for managing
  	xbd_qfrozen_cnt and use them to implement all queue freezing logic.
  
  	Add missing "thaw" to restart I/O processing once grant references
  	become available.
  
  Sponsored by:	Spectra Logic Corporation

Modified:
  head/sys/dev/xen/blkfront/blkfront.c
  head/sys/dev/xen/blkfront/block.h

Modified: head/sys/dev/xen/blkfront/blkfront.c
==============================================================================
--- head/sys/dev/xen/blkfront/blkfront.c	Sat Jun 15 04:45:33 2013	(r251771)
+++ head/sys/dev/xen/blkfront/blkfront.c	Sat Jun 15 04:51:31 2013	(r251772)
@@ -87,6 +87,30 @@ static void xbd_startio(struct xbd_softc
 static MALLOC_DEFINE(M_XENBLOCKFRONT, "xbd", "Xen Block Front driver data");
 
 /*---------------------------- Command Processing ----------------------------*/
+static void
+xbd_freeze(struct xbd_softc *sc, xbd_flag_t xbd_flag)
+{
+	if (xbd_flag != XBDF_NONE && (sc->xbd_flags & xbd_flag) != 0)
+		return;
+
+	sc->xbd_flags |= xbd_flag;
+	sc->xbd_qfrozen_cnt++;
+}
+
+static void
+xbd_thaw(struct xbd_softc *sc, xbd_flag_t xbd_flag)
+{
+	if (xbd_flag != XBDF_NONE && (sc->xbd_flags & xbd_flag) == 0)
+		return;
+
+	if (sc->xbd_qfrozen_cnt != 0)
+		panic("%s: Thaw with flag 0x%x while not frozen.",
+		    __func__, xbd_flag);
+
+	sc->xbd_flags &= ~xbd_flag;
+	sc->xbd_qfrozen_cnt--;
+}
+
 static inline void 
 xbd_flush_requests(struct xbd_softc *sc)
 {
@@ -110,6 +134,7 @@ xbd_free_command(struct xbd_command *cm)
 	cm->cm_bp = NULL;
 	cm->cm_complete = NULL;
 	xbd_enqueue_cm(cm, XBD_Q_FREE);
+	xbd_thaw(cm->cm_sc, XBDF_CM_SHORTAGE);
 }
 
 static void
@@ -212,10 +237,13 @@ xbd_queue_cb(void *arg, bus_dma_segment_
 	xbd_enqueue_cm(cm, XBD_Q_BUSY);
 
 	/*
-	 * This flag means that we're probably executing in the busdma swi
-	 * instead of in the startio context, so an explicit flush is needed.
+	 * If bus dma had to asynchronously call us back to dispatch
+	 * this command, we are no longer executing in the context of 
+	 * xbd_startio().  Thus we cannot rely on xbd_startio()'s call to
+	 * xbd_flush_requests() to publish this command to the backend
+	 * along with any other commands that it could batch.
 	 */
-	if (cm->cm_flags & XBDCF_FROZEN)
+	if ((cm->cm_flags & XBDCF_ASYNC_MAPPING) != 0)
 		xbd_flush_requests(sc);
 
 	return;
@@ -229,9 +257,14 @@ xbd_queue_request(struct xbd_softc *sc, 
 	error = bus_dmamap_load(sc->xbd_io_dmat, cm->cm_map, cm->cm_data,
 	    cm->cm_datalen, xbd_queue_cb, cm, 0);
 	if (error == EINPROGRESS) {
-		printf("EINPROGRESS\n");
-		sc->xbd_flags |= XBDF_FROZEN;
-		cm->cm_flags |= XBDCF_FROZEN;
+		/*
+		 * Maintain queuing order by freezing the queue.  The next
+		 * command may not require as many resources as the command
+		 * we just attempted to map, so we can't rely on bus dma
+		 * blocking for it too.
+		 */
+		xbd_freeze(sc, XBDF_NONE);
+		cm->cm_flags |= XBDCF_FROZEN|XBDCF_ASYNC_MAPPING;
 		return (0);
 	}
 
@@ -245,6 +278,8 @@ xbd_restart_queue_callback(void *arg)
 
 	mtx_lock(&sc->xbd_io_lock);
 
+	xbd_thaw(sc, XBDF_GNT_SHORTAGE);
+
 	xbd_startio(sc);
 
 	mtx_unlock(&sc->xbd_io_lock);
@@ -264,6 +299,7 @@ xbd_bio_command(struct xbd_softc *sc)
 		return (NULL);
 
 	if ((cm = xbd_dequeue_cm(sc, XBD_Q_FREE)) == NULL) {
+		xbd_freeze(sc, XBDF_CM_SHORTAGE);
 		xbd_requeue_bio(sc, bp);
 		return (NULL);
 	}
@@ -273,9 +309,9 @@ xbd_bio_command(struct xbd_softc *sc)
 		gnttab_request_free_callback(&sc->xbd_callback,
 		    xbd_restart_queue_callback, sc,
 		    sc->xbd_max_request_segments);
+		xbd_freeze(sc, XBDF_GNT_SHORTAGE);
 		xbd_requeue_bio(sc, bp);
 		xbd_enqueue_cm(cm, XBD_Q_FREE);
-		sc->xbd_flags |= XBDF_FROZEN;
 		return (NULL);
 	}
 
@@ -309,7 +345,7 @@ xbd_startio(struct xbd_softc *sc)
 
 	while (RING_FREE_REQUESTS(&sc->xbd_ring) >=
 	    sc->xbd_max_request_blocks) {
-		if (sc->xbd_flags & XBDF_FROZEN)
+		if (sc->xbd_qfrozen_cnt != 0)
 			break;
 
 		cm = xbd_dequeue_cm(sc, XBD_Q_READY);
@@ -397,11 +433,13 @@ xbd_int(void *xsc)
 		bus_dmamap_unload(sc->xbd_io_dmat, cm->cm_map);
 
 		/*
-		 * If commands are completing then resources are probably
-		 * being freed as well.  It's a cheap assumption even when
-		 * wrong.
+		 * Release any hold this command has on future command
+		 * dispatch. 
 		 */
-		sc->xbd_flags &= ~XBDF_FROZEN;
+		if ((cm->cm_flags & XBDCF_FROZEN) != 0) {
+			xbd_thaw(sc, XBDF_NONE);
+			cm->cm_flags &= ~XBDCF_FROZEN;
+		}
 
 		/*
 		 * Directly call the i/o complete routine to save an

Modified: head/sys/dev/xen/blkfront/block.h
==============================================================================
--- head/sys/dev/xen/blkfront/block.h	Sat Jun 15 04:45:33 2013	(r251771)
+++ head/sys/dev/xen/blkfront/block.h	Sat Jun 15 04:51:31 2013	(r251772)
@@ -96,6 +96,7 @@ typedef enum {
 	XBDCF_Q_MASK		= 0xFF,
 	XBDCF_FROZEN		= 1<<8,
 	XBDCF_POLLED		= 1<<9,
+	XBDCF_ASYNC_MAPPING	= 1<<10,
 	XBDCF_INITIALIZER	= XBDCF_Q_MASK
 } xbdc_flag_t;
 
@@ -143,10 +144,12 @@ typedef enum {
 } xbd_state_t;
 
 typedef enum {
-	XBDF_OPEN	= 1 << 0,	/* drive is open (can't shut down) */
-	XBDF_BARRIER	= 1 << 1,	/* backend supports barriers */
-	XBDF_READY	= 1 << 2,	/* Is ready */
-	XBDF_FROZEN	= 1 << 3	/* Waiting for resources */
+	XBDF_NONE	  = 0,
+	XBDF_OPEN	  = 1 << 0, /* drive is open (can't shut down) */
+	XBDF_BARRIER	  = 1 << 1, /* backend supports barriers */
+	XBDF_READY	  = 1 << 2, /* Is ready */
+	XBDF_CM_SHORTAGE  = 1 << 3, /* Free cm resource shortage active. */
+	XBDF_GNT_SHORTAGE = 1 << 4  /* Grant ref resource shortage active */
 } xbd_flag_t;
 
 /*
@@ -158,6 +161,7 @@ struct xbd_softc {
 	struct bio_queue_head 		 xbd_bioq;	/* sort queue */
 	int				 xbd_unit;
 	xbd_flag_t			 xbd_flags;
+	int				 xbd_qfrozen_cnt;
 	int				 xbd_vdevice;
 	xbd_state_t			 xbd_state;
 	u_int				 xbd_ring_pages;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306150451.r5F4pWJm023492>