summaryrefslogtreecommitdiff
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
authorSepherosa Ziehau <sephe@FreeBSD.org>2016-11-25 09:13:10 +0000
committerSepherosa Ziehau <sephe@FreeBSD.org>2016-11-25 09:13:10 +0000
commit2641e757426b0b92d46421eeceb63f24ac002566 (patch)
treeb2544e2fbeafc60579b74657633e0f48b157624d /sys/dev/hyperv/vmbus
parent892b35bc36c3b931d99301cbf751c503726db0ce (diff)
Notes
Diffstat (limited to 'sys/dev/hyperv/vmbus')
-rw-r--r--sys/dev/hyperv/vmbus/vmbus_chan.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c
index 4364ac7be837..18f83aa5dbbc 100644
--- a/sys/dev/hyperv/vmbus/vmbus_chan.c
+++ b/sys/dev/hyperv/vmbus/vmbus_chan.c
@@ -851,6 +851,41 @@ disconnect:
return (error);
}
+int
+vmbus_chan_close_direct(struct vmbus_channel *chan)
+{
+ int error;
+
+#ifdef INVARIANTS
+ if (VMBUS_CHAN_ISPRIMARY(chan)) {
+ struct vmbus_channel *subchan;
+
+ /*
+ * All sub-channels _must_ have been closed, or are _not_
+ * opened at all.
+ */
+ mtx_lock(&chan->ch_subchan_lock);
+ TAILQ_FOREACH(subchan, &chan->ch_subchans, ch_sublink) {
+ KASSERT(
+ (subchan->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0,
+ ("chan%u: subchan%u is still opened",
+ chan->ch_id, subchan->ch_subidx));
+ }
+ mtx_unlock(&chan->ch_subchan_lock);
+ }
+#endif
+
+ error = vmbus_chan_close_internal(chan);
+ if (!VMBUS_CHAN_ISPRIMARY(chan)) {
+ /*
+ * This sub-channel is referenced, when it is linked to
+ * the primary channel; drop that reference now.
+ */
+ vmbus_chan_detach(chan);
+ }
+ return (error);
+}
+
/*
* Caller should make sure that all sub-channels have
* been added to 'chan' and all to-be-closed channels