Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Nov 2016 04:58:13 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r309080 - in head/sys/dev/hyperv: include vmbus
Message-ID:  <201611240458.uAO4wD4e039786@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Nov 24 04:58:13 2016
New Revision: 309080
URL: https://svnweb.freebsd.org/changeset/base/309080

Log:
  hyperv/vmbus: Implement orphan support for transaction API
  
  It will be used to fix the primary channel revocation support.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D8525

Modified:
  head/sys/dev/hyperv/include/vmbus_xact.h
  head/sys/dev/hyperv/vmbus/vmbus_xact.c

Modified: head/sys/dev/hyperv/include/vmbus_xact.h
==============================================================================
--- head/sys/dev/hyperv/include/vmbus_xact.h	Thu Nov 24 01:24:26 2016	(r309079)
+++ head/sys/dev/hyperv/include/vmbus_xact.h	Thu Nov 24 04:58:13 2016	(r309080)
@@ -39,6 +39,8 @@ struct vmbus_xact_ctx	*vmbus_xact_ctx_cr
 			    size_t req_size, size_t resp_size,
 			    size_t priv_size);
 void			vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx);
+bool			vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx);
+
 struct vmbus_xact	*vmbus_xact_get(struct vmbus_xact_ctx *ctx,
 			    size_t req_len);
 void			vmbus_xact_put(struct vmbus_xact *xact);

Modified: head/sys/dev/hyperv/vmbus/vmbus_xact.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_xact.c	Thu Nov 24 01:24:26 2016	(r309079)
+++ head/sys/dev/hyperv/vmbus/vmbus_xact.c	Thu Nov 24 04:58:13 2016	(r309080)
@@ -61,6 +61,7 @@ struct vmbus_xact_ctx {
 	uint32_t			xc_flags;	/* VMBUS_XACT_CTXF_ */
 	struct vmbus_xact		*xc_free;
 	struct vmbus_xact		*xc_active;
+	struct vmbus_xact		*xc_orphan;
 };
 
 #define VMBUS_XACT_CTXF_DESTROY		0x0001
@@ -72,6 +73,9 @@ static struct vmbus_xact	*vmbus_xact_get
 				    uint32_t);
 const void			*vmbus_xact_wait1(struct vmbus_xact *, size_t *,
 				    bool);
+static void			vmbus_xact_save_resp(struct vmbus_xact *,
+				    const void *, size_t);
+static void			vmbus_xact_ctx_free(struct vmbus_xact_ctx *);
 
 static struct vmbus_xact *
 vmbus_xact_alloc(struct vmbus_xact_ctx *ctx, bus_dma_tag_t parent_dtag)
@@ -136,6 +140,9 @@ vmbus_xact_ctx_create(bus_dma_tag_t dtag
 {
 	struct vmbus_xact_ctx *ctx;
 
+	KASSERT(req_size > 0, ("request size is 0"));
+	KASSERT(resp_size > 0, ("response size is 0"));
+
 	ctx = malloc(sizeof(*ctx), M_DEVBUF, M_WAITOK | M_ZERO);
 	ctx->xc_req_size = req_size;
 	ctx->xc_resp_size = resp_size;
@@ -152,25 +159,46 @@ vmbus_xact_ctx_create(bus_dma_tag_t dtag
 	return (ctx);
 }
 
-void
-vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx)
+bool
+vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx)
 {
-	struct vmbus_xact *xact;
-
 	mtx_lock(&ctx->xc_lock);
+	if (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) {
+		mtx_unlock(&ctx->xc_lock);
+		return (false);
+	}
 	ctx->xc_flags |= VMBUS_XACT_CTXF_DESTROY;
 	mtx_unlock(&ctx->xc_lock);
+
 	wakeup(&ctx->xc_free);
+	wakeup(&ctx->xc_active);
 
-	xact = vmbus_xact_get1(ctx, 0);
-	if (xact == NULL)
+	ctx->xc_orphan = vmbus_xact_get1(ctx, 0);
+	if (ctx->xc_orphan == NULL)
 		panic("can't get xact");
+	return (true);
+}
+
+static void
+vmbus_xact_ctx_free(struct vmbus_xact_ctx *ctx)
+{
+	KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY,
+	    ("xact ctx was not orphaned"));
+	KASSERT(ctx->xc_orphan != NULL, ("no orphaned xact"));
 
-	vmbus_xact_free(xact);
+	vmbus_xact_free(ctx->xc_orphan);
 	mtx_destroy(&ctx->xc_lock);
 	free(ctx, M_DEVBUF);
 }
 
+void
+vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx)
+{
+
+	vmbus_xact_ctx_orphan(ctx);
+	vmbus_xact_ctx_free(ctx);
+}
+
 struct vmbus_xact *
 vmbus_xact_get(struct vmbus_xact_ctx *ctx, size_t req_len)
 {
@@ -259,7 +287,8 @@ vmbus_xact_wait1(struct vmbus_xact *xact
 	mtx_lock(&ctx->xc_lock);
 
 	KASSERT(ctx->xc_active == xact, ("xact mismatch"));
-	while (xact->x_resp == NULL) {
+	while (xact->x_resp == NULL &&
+	    (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) {
 		if (can_sleep) {
 			mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0,
 			    "wxact", 0);
@@ -269,6 +298,20 @@ vmbus_xact_wait1(struct vmbus_xact *xact
 			mtx_lock(&ctx->xc_lock);
 		}
 	}
+	KASSERT(ctx->xc_active == xact, ("xact trashed"));
+
+	if ((ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) && xact->x_resp == NULL) {
+		uint8_t b = 0;
+
+		/*
+		 * Orphaned and no response was received yet; fake up
+		 * an one byte response.
+		 */
+		printf("vmbus: xact ctx was orphaned w/ pending xact\n");
+		vmbus_xact_save_resp(ctx->xc_active, &b, sizeof(b));
+	}
+	KASSERT(xact->x_resp != NULL, ("no response"));
+
 	ctx->xc_active = NULL;
 
 	resp = xact->x_resp;
@@ -317,19 +360,47 @@ void
 vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen)
 {
 	struct vmbus_xact_ctx *ctx = xact->x_ctx;
+	int do_wakeup = 0;
 
 	mtx_lock(&ctx->xc_lock);
-	vmbus_xact_save_resp(xact, data, dlen);
+	/*
+	 * NOTE:
+	 * xc_active could be NULL, if the ctx has been orphaned.
+	 */
+	if (ctx->xc_active != NULL) {
+		vmbus_xact_save_resp(xact, data, dlen);
+		do_wakeup = 1;
+	} else {
+		KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY,
+		    ("no active xact pending"));
+		printf("vmbus: drop xact response\n");
+	}
 	mtx_unlock(&ctx->xc_lock);
-	wakeup(&ctx->xc_active);
+
+	if (do_wakeup)
+		wakeup(&ctx->xc_active);
 }
 
 void
 vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, const void *data, size_t dlen)
 {
+	int do_wakeup = 0;
+
 	mtx_lock(&ctx->xc_lock);
-	KASSERT(ctx->xc_active != NULL, ("no pending xact"));
-	vmbus_xact_save_resp(ctx->xc_active, data, dlen);
+	/*
+	 * NOTE:
+	 * xc_active could be NULL, if the ctx has been orphaned.
+	 */
+	if (ctx->xc_active != NULL) {
+		vmbus_xact_save_resp(ctx->xc_active, data, dlen);
+		do_wakeup = 1;
+	} else {
+		KASSERT(ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY,
+		    ("no active xact pending"));
+		printf("vmbus: drop xact response\n");
+	}
 	mtx_unlock(&ctx->xc_lock);
-	wakeup(&ctx->xc_active);
+
+	if (do_wakeup)
+		wakeup(&ctx->xc_active);
 }



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