svn commit: r309135 - in head/sys/dev/hyperv: include vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Fri Nov 25 07:24:12 UTC 2016
Author: sephe
Date: Fri Nov 25 07:24:11 2016
New Revision: 309135
URL: https://svnweb.freebsd.org/changeset/base/309135
Log:
hyperv/vmbus: Return EISCONN if the bufring GPADL can't be disconnected.
So that the callers of vmbus_chan_open_br() could handle the passed in
bufring memory properly.
MFC after: 1 week
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D8569
Modified:
head/sys/dev/hyperv/include/vmbus.h
head/sys/dev/hyperv/vmbus/vmbus_chan.c
Modified: head/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- head/sys/dev/hyperv/include/vmbus.h Fri Nov 25 07:03:45 2016 (r309134)
+++ head/sys/dev/hyperv/include/vmbus.h Fri Nov 25 07:24:11 2016 (r309135)
@@ -129,6 +129,17 @@ vmbus_get_channel(device_t dev)
return device_get_ivars(dev);
}
+/*
+ * vmbus_chan_open_br()
+ * Return values:
+ * 0 Succeeded.
+ * EISCONN Failed, and the memory passed through 'br' is still
+ * connected. Callers must _not_ free the the memory
+ * passed through 'br', if this error happens.
+ * other values Failed. The memory passed through 'br' is no longer
+ * connected. Callers are free to do anything with the
+ * memory passed through 'br'.
+ */
int vmbus_chan_open(struct vmbus_channel *chan,
int txbr_size, int rxbr_size, const void *udata, int udlen,
vmbus_chan_callback_t cb, void *cbarg);
Modified: head/sys/dev/hyperv/vmbus/vmbus_chan.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_chan.c Fri Nov 25 07:03:45 2016 (r309134)
+++ head/sys/dev/hyperv/vmbus/vmbus_chan.c Fri Nov 25 07:24:11 2016 (r309135)
@@ -324,7 +324,21 @@ vmbus_chan_open(struct vmbus_channel *ch
error = vmbus_chan_open_br(chan, &cbr, udata, udlen, cb, cbarg);
if (error) {
- hyperv_dmamem_free(&chan->ch_bufring_dma, chan->ch_bufring);
+ if (error == EISCONN) {
+ /*
+ * XXX
+ * The bufring GPADL is still connected; abandon
+ * this bufring, instead of having mysterious
+ * crash or trashed data later on.
+ */
+ vmbus_chan_printf(chan, "chan%u bufring GPADL "
+ "is still connected upon channel open error; "
+ "leak %d bytes memory\n", chan->ch_id,
+ txbr_size + rxbr_size);
+ } else {
+ hyperv_dmamem_free(&chan->ch_bufring_dma,
+ chan->ch_bufring);
+ }
chan->ch_bufring = NULL;
}
return (error);
@@ -458,7 +472,17 @@ failed:
sysctl_ctx_free(&chan->ch_sysctl_ctx);
vmbus_chan_clear_chmap(chan);
if (chan->ch_bufring_gpadl != 0) {
- vmbus_chan_gpadl_disconnect(chan, chan->ch_bufring_gpadl);
+ int error1;
+
+ error1 = vmbus_chan_gpadl_disconnect(chan,
+ chan->ch_bufring_gpadl);
+ if (error1) {
+ /*
+ * Give caller a hint that the bufring GPADL is still
+ * connected.
+ */
+ error = EISCONN;
+ }
chan->ch_bufring_gpadl = 0;
}
atomic_clear_int(&chan->ch_stflags, VMBUS_CHAN_ST_OPENED);
More information about the svn-src-head
mailing list