svn commit: r361360 - head/sys/dev/hyperv/hvsock
Wei Hu
weh at microsoft.com
Tue Jun 2 14:29:58 UTC 2020
> -----Original Message-----
> From: Kyle Evans <kevans at freebsd.org>
> Sent: Saturday, May 30, 2020 4:34 AM
> To: Wei Hu <whu at freebsd.org>
> Cc: src-committers <src-committers at freebsd.org>; svn-src-all <svn-src-
> all at freebsd.org>; svn-src-head <svn-src-head at freebsd.org>
> Subject: Re: svn commit: r361360 - head/sys/dev/hyperv/hvsock
>
> On Fri, May 22, 2020 at 10:51 AM Kyle Evans <kevans at freebsd.org> wrote:
> >
> > On Fri, May 22, 2020 at 4:17 AM Wei Hu <whu at freebsd.org> wrote:
> > >
> > > Author: whu
> > > Date: Fri May 22 09:17:07 2020
> > > New Revision: 361360
> > > URL:
> > > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsv
> > >
> nweb.freebsd.org%2Fchangeset%2Fbase%2F361360&data=02%7C01%7C
> weh%
> > >
> 40microsoft.com%7Cc97d2dddd23b440a8f1708d8040f9563%7C72f988bf86f1
> 41a
> > >
> f91ab2d7cd011db47%7C1%7C0%7C637263812262686264&sdata=xPJ95
> nVsWPV
> > > f8qxlxSyMplJXuaFcbp5bd9FiGgvHhao%3D&reserved=0
> > >
> > > Log:
> > > Socket AF_HYPERV should return failure when it is not running on
> > > HyperV
> > >
> > > [... snip ...]
> > > @@ -354,6 +354,9 @@ hvs_trans_attach(struct socket *so, int proto,
> > > struct {
> > > struct hvs_pcb *pcb = so2hvspcb(so);
> > >
> > > + if (vm_guest != VM_GUEST_HV)
> > > + return (ESOCKTNOSUPPORT);
> > > +
> > > HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> > > "%s: HyperV Socket hvs_trans_attach called\n",
> > > __func__);
> > >
> >
> > This one may be OK, but none of these other methods should be able to
> > be invoked if the attach failed. See this comment at around
> > ^/sys/kern/uipc_socket.c#50:
> >
> > 50 * pru_detach() disassociates protocol layer state from an attached
> > socket,
> > 51 * and will be called exactly once for sockets in which pru_attach()
> > has
> > 52 * been successfully called. If pru_attach() returned an error,
> > 53 * pru_detach() will not be called. Socket layer private.
> >
> > That said, I wonder if VNET_DOMAIN_SET provides the correct semantics
> > here at all. You can't fail domain_init, but I don't think there's any
> > value in this domain actually getting registered on non-HyperV guests,
> > a fact which presumably won't change at runtime.
> >
>
> I'm considering the patch below, which is almost certainly going to be mangled
> by my mail client, for solving this style of problem. It gives the domain a chance
> to probe the system and opt out, for cases like hvsock where leaving the
> domain around and fully-initialized when there's no way it can work is both
> wasteful and a bit of an accident waiting to happen -- IMO it's much less error
> prone and more comforting if we just reject it early on, since we can. The
> vm_guest detection and hyperv's false-positive aversion stuff in hyperv_init
> should run much earlier than this.
>
> diff --git a/sys/dev/hyperv/hvsock/hv_sock.c
> b/sys/dev/hyperv/hvsock/hv_sock.c index d212c2d8c2d..d3bc1ab0f2c 100644
> --- a/sys/dev/hyperv/hvsock/hv_sock.c
> +++ b/sys/dev/hyperv/hvsock/hv_sock.c
> @@ -74,6 +74,8 @@ SYSCTL_INT(_net_hvsock, OID_AUTO, hvs_dbg_level,
> CTLFLAG_RWTUN, &hvs_dbg_level,
>
> MALLOC_DEFINE(M_HVSOCK, "hyperv_socket", "hyperv socket control
> structures");
>
> +static int hvs_dom_probe(void);
> +
> /* The MTU is 16KB per host side's design */
> #define HVSOCK_MTU_SIZE (1024 * 16)
> #define HVSOCK_SEND_BUF_SZ (PAGE_SIZE - sizeof(struct
> vmpipe_proto_header))
> @@ -124,6 +126,7 @@ static struct protosw hv_socket_protosw[] = {
> static struct domain hv_socket_domain = {
> .dom_family = AF_HYPERV,
> .dom_name = "hyperv",
> + .dom_probe = hvs_dom_probe,
> .dom_protosw = hv_socket_protosw,
> .dom_protoswNPROTOSW =
> &hv_socket_protosw[nitems(hv_socket_protosw)]
> };
> @@ -322,6 +325,16 @@ hvs_trans_unlock(void)
> sx_xunlock(&hvs_trans_socks_sx); }
>
> +static int
> +hvs_dom_probe(void)
> +{
> +
> + /* Don't even give us a chance to attach on non-HyperV. */
> + if (vm_guest != VM_GUEST_HV)
> + return (ENXIO);
> + return (0);
> +}
> +
> void
> hvs_trans_init(void)
> {
> @@ -329,9 +342,6 @@ hvs_trans_init(void)
> if (!IS_DEFAULT_VNET(curvnet))
> return;
>
> - if (vm_guest != VM_GUEST_HV)
> - return;
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_init called\n", __func__);
>
> @@ -354,9 +364,6 @@ hvs_trans_attach(struct socket *so, int proto, struct
> thread *td) {
> struct hvs_pcb *pcb = so2hvspcb(so);
>
> - if (vm_guest != VM_GUEST_HV)
> - return (ESOCKTNOSUPPORT);
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_attach called\n", __func__);
>
> @@ -383,9 +390,6 @@ hvs_trans_detach(struct socket *so) {
> struct hvs_pcb *pcb;
>
> - if (vm_guest != VM_GUEST_HV)
> - return;
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_detach called\n", __func__);
>
> @@ -595,9 +599,6 @@ hvs_trans_disconnect(struct socket *so) {
> struct hvs_pcb *pcb;
>
> - if (vm_guest != VM_GUEST_HV)
> - return (ESOCKTNOSUPPORT);
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_disconnect called\n", __func__);
>
> @@ -925,9 +926,6 @@ hvs_trans_close(struct socket *so) {
> struct hvs_pcb *pcb;
>
> - if (vm_guest != VM_GUEST_HV)
> - return;
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_close called\n", __func__);
>
> @@ -969,9 +967,6 @@ hvs_trans_abort(struct socket *so) {
> struct hvs_pcb *pcb = so2hvspcb(so);
>
> - if (vm_guest != VM_GUEST_HV)
> - return;
> -
> HVSOCK_DBG(HVSOCK_DBG_VERBOSE,
> "%s: HyperV Socket hvs_trans_abort called\n", __func__);
>
> diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index
> 60e30eb1ae0..63217566ba9 100644
> --- a/sys/kern/uipc_domain.c
> +++ b/sys/kern/uipc_domain.c
> @@ -170,9 +170,13 @@ protosw_init(struct protosw *pr) void
> domain_init(void *arg) {
> - struct domain *dp = arg;
> + struct domain_set_args *dsa = arg;
> + struct domain *dp;
> struct protosw *pr;
>
> + if (!dsa->dsa_supported)
> + return;
> + dp = dsa->dsa_dp;
> if (dp->dom_init)
> (*dp->dom_init)();
> for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) @@
> -198,8 +202,12 @@ vnet_domain_init(void *arg) void
> vnet_domain_uninit(void *arg) {
> - struct domain *dp = arg;
> + struct domain_set_args *dsa = arg;
> + struct domain *dp;
>
> + if (!dsa->dsa_supported)
> + return;
> + dp = dsa->dsa_dp;
> if (dp->dom_destroy)
> (*dp->dom_destroy)();
> }
> @@ -213,9 +221,14 @@ vnet_domain_uninit(void *arg) void
> domain_add(void *data) {
> + struct domain_set_args *dsa;
> struct domain *dp;
>
> - dp = (struct domain *)data;
> + dsa = data;
> + dp = dsa->dsa_dp;
> + if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0)
> + return;
> + dsa->dsa_supported = 1;
> mtx_lock(&dom_mtx);
> dp->dom_next = domains;
> domains = dp;
> diff --git a/sys/sys/domain.h b/sys/sys/domain.h index
> e83dd0f4afc..11211f072c2 100644
> --- a/sys/sys/domain.h
> +++ b/sys/sys/domain.h
> @@ -49,6 +49,7 @@ struct socket;
> struct domain {
> int dom_family; /* AF_xxx */
> char *dom_name;
> + int (*dom_probe)(void); /* check for support (optional) */
> void (*dom_init) /* initialize domain data structures */
> (void);
> void (*dom_destroy) /* cleanup structures / state */
> @@ -79,20 +80,36 @@ void vnet_domain_init(void *);
> void vnet_domain_uninit(void *);
> #endif
>
> +struct domain_set_args {
> + struct domain *dsa_dp;
> + int dsa_supported;
> +};
> +
> #define DOMAIN_SET(name)
> \
> + static struct domain_set_args name ## domain_set_args = { \
> + .dsa_dp = & name ## domain, \
> + }; \
> SYSINIT(domain_add_ ## name, SI_SUB_PROTO_DOMAIN, \
> - SI_ORDER_FIRST, domain_add, & name ## domain); \
> + SI_ORDER_FIRST, domain_add, &name ## domain_set_args); \
> SYSINIT(domain_init_ ## name, SI_SUB_PROTO_DOMAIN, \
> - SI_ORDER_SECOND, domain_init, & name ## domain);
> + SI_ORDER_SECOND, domain_init, &name ## domain_set_args);
> #ifdef VIMAGE
> +/*
> + * There's no such thing as per-vnet domains, so domain_set_args don't
> +really
> + * need to be virtualized at the moment. Further consideration would
> +be needed
> + * for such a concept to work at all.
> + */
> #define VNET_DOMAIN_SET(name)
> \
> + static struct domain_set_args name ## domain_set_args = { \
> + .dsa_dp = & name ## domain, \
> + }; \
> SYSINIT(domain_add_ ## name, SI_SUB_PROTO_DOMAIN, \
> - SI_ORDER_FIRST, domain_add, & name ## domain); \
> + SI_ORDER_FIRST, domain_add, &name ## domain_set_args); \
> VNET_SYSINIT(vnet_domain_init_ ## name, SI_SUB_PROTO_DOMAIN, \
> - SI_ORDER_SECOND, vnet_domain_init, & name ## domain); \
> + SI_ORDER_SECOND, vnet_domain_init, &name ##
> + domain_set_args); \
> VNET_SYSUNINIT(vnet_domain_uninit_ ## name, \
> SI_SUB_PROTO_DOMAIN, SI_ORDER_SECOND, vnet_domain_uninit, \
> - & name ## domain)
> + &name ## domain_set_args);
> #else /* !VIMAGE */
> #define VNET_DOMAIN_SET(name) DOMAIN_SET(name)
> #endif /* VIMAGE */
Thanks Kyle. It makes a lot of sense if it can be rejected as early as possible when it
is not on HyperV. I am fine with the changes in the hvsock. The changes made in
uipc_domain.c and domain.h may need more eyes to review from VIMAGE
perspective.
Thanks,
Wei
More information about the svn-src-all
mailing list