summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2014-06-09 22:00:01 +0000
committerRobert Mustacchi <rm@joyent.com>2014-06-11 15:47:28 +0000
commitc500bd9d9ae9d89503ceae50d323c9b76c6dbefc (patch)
tree3801d34d3889fdafb0da408c501efb124bb1bf4f
parent11d59699e68c04247915387555a99ec83d29f772 (diff)
downloadillumos-joyent-c500bd9d9ae9d89503ceae50d323c9b76c6dbefc.tar.gz
OS-3094 vnd race between stream association and first data
-rw-r--r--usr/src/uts/common/io/vnd/vnd.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/usr/src/uts/common/io/vnd/vnd.c b/usr/src/uts/common/io/vnd/vnd.c
index 7d5f43e658..9c86c85a4c 100644
--- a/usr/src/uts/common/io/vnd/vnd.c
+++ b/usr/src/uts/common/io/vnd/vnd.c
@@ -913,6 +913,10 @@ static uint8_t vnd_ipv6_mcast[2] = { 0x33, 0x33 };
* vnd internal data structures and types
*/
+struct vnd_str;
+struct vnd_dev;
+struct vnd_pnsd;
+
/*
* As part of opening the device stream we need to properly communicate with our
* underlying stream. This is a bit of an asynchronous dance and we need to
@@ -955,6 +959,8 @@ typedef enum vnd_capab_flags {
/*
* Definitions to interact with direct callbacks
*/
+typedef void (*vnd_rx_t)(struct vnd_str *, mac_resource_t *, mblk_t *,
+ mac_header_info_t *);
typedef uintptr_t vnd_mac_cookie_t;
/* DLD Direct capability function */
typedef int (*vnd_dld_cap_t)(void *, uint_t, void *, uint_t);
@@ -984,10 +990,6 @@ typedef struct vnd_str_capab {
void *vsc_tx_fc_hdl;
} vnd_str_capab_t;
-struct vnd_str;
-struct vnd_dev;
-struct vnd_pnsd;
-
/*
* The vnd_data_queue is a simple construct for storing a series of messages in
* a queue.
@@ -1207,6 +1209,19 @@ vnd_drop_panic(vnd_str_t *vsp, mblk_t *mp, const char *reason)
panic("illegal vnd drop");
}
+static void
+vnd_mac_drop_input(vnd_str_t *vsp, mac_resource_t *unused, mblk_t *mp_chain,
+ mac_header_info_t *mhip)
+{
+ mblk_t *mp;
+
+ while (mp_chain != NULL) {
+ mp = mp_chain;
+ mp_chain = mp->b_next;
+ vnd_drop_hook_in(vsp, mp, "stream not associated");
+ }
+}
+
static vnd_pnsd_t *
vnd_nsd_lookup(netstackid_t nsid)
{
@@ -2052,7 +2067,7 @@ vnd_st_scapabq(vnd_str_t *vsp)
}
static void
-vnd_mac_input(vnd_str_t *vsp, mac_resource_t *wtf, mblk_t *mp_chain,
+vnd_mac_input(vnd_str_t *vsp, mac_resource_t *unused, mblk_t *mp_chain,
mac_header_info_t *mhip)
{
int signal = 0;
@@ -2191,7 +2206,7 @@ vnd_mac_exit(vnd_str_t *vsp, mac_perim_handle_t mph)
}
static int
-vnd_dld_cap_enable(vnd_str_t *vsp)
+vnd_dld_cap_enable(vnd_str_t *vsp, vnd_rx_t rxfunc)
{
int ret;
dld_capab_direct_t d;
@@ -2199,7 +2214,7 @@ vnd_dld_cap_enable(vnd_str_t *vsp)
vnd_str_capab_t *c = &vsp->vns_caps;
bzero(&d, sizeof (d));
- d.di_rx_cf = (uintptr_t)vnd_mac_input;
+ d.di_rx_cf = (uintptr_t)rxfunc;
d.di_rx_ch = vsp;
d.di_flags = DI_DIRECT_RAW;
@@ -2303,7 +2318,14 @@ vnd_st_capabq(vnd_str_t *vsp)
(vnd_dld_cap_t)dld->dld_capab;
vsp->vns_caps.vsc_capab_hdl =
(void *)dld->dld_capab_handle;
- if (vnd_dld_cap_enable(vsp) != 0) {
+ /*
+ * At this point in time, we have to set up a direct
+ * function that drops all input. This validates that
+ * we'll be able to set up direct input and that we can
+ * easily switch it earlier to the real data function
+ * when we've plumbed everything up.
+ */
+ if (vnd_dld_cap_enable(vsp, vnd_mac_drop_input) != 0) {
/* vns_errno set by vnd_dld_cap_enable */
ret = 1;
goto done;
@@ -3048,6 +3070,21 @@ vnd_striocdata(queue_t *q, vnd_str_t *vsp, mblk_t *mp, struct copyresp *csp)
vdp->vdd_str = vsp;
vsp->vns_dev = vdp;
+ /*
+ * Now, it's time to do the las thing that can fail, changing out the
+ * input function. After this we know that we can receive data, so we
+ * should make sure that we're ready.
+ */
+ if (vnd_dld_cap_enable(vsp, vnd_mac_input) != 0) {
+ error = EIO;
+ vss->vsa_errno = VND_E_DIRECTFAIL;
+ vdp->vdd_str = NULL;
+ vsp->vns_dev = NULL;
+ mutex_exit(&vsp->vns_lock);
+ mutex_exit(&vdp->vdd_lock);
+ goto nak;
+ }
+
zone = zone_find_by_id(vdp->vdd_nsd->vpnd_zid);
ASSERT(zone != NULL);
vsp->vns_kstat->ks_data = &vsp->vns_ksdata;