From owner-svn-src-all@FreeBSD.ORG Sat Jun 15 04:51:32 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 7ED362DB; Sat, 15 Jun 2013 04:51:32 +0000 (UTC) (envelope-from gibbs@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6F1181921; Sat, 15 Jun 2013 04:51:32 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r5F4pWJK023494; Sat, 15 Jun 2013 04:51:32 GMT (envelope-from gibbs@svn.freebsd.org) Received: (from gibbs@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r5F4pWJm023492; Sat, 15 Jun 2013 04:51:32 GMT (envelope-from gibbs@svn.freebsd.org) Message-Id: <201306150451.r5F4pWJm023492@svn.freebsd.org> From: "Justin T. Gibbs" Date: Sat, 15 Jun 2013 04:51:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r251772 - head/sys/dev/xen/blkfront X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 15 Jun 2013 04:51:32 -0000 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;