You have M_WAITOK and a null check in this change
On Mon, 2 Jul 2018 at 06:20, Matt Macy wrote:
> Author: mmacy
> Date: Mon Jul 2 05:19:44 2018
> New Revision: 335856
> URL: https://svnweb.freebsd.org/changeset/base/335856
>
> Log:
> inpcb: don't gratuitously defer frees
>
> Don't defer frees in sysctl handlers. It isn't necessary
> and it just confuses things.
> revert: r333911, r334104, and r334125
>
> Requested by: jtl
>
> Modified:
> head/sys/netinet/ip_divert.c
> head/sys/netinet/raw_ip.c
> head/sys/netinet/tcp_subr.c
> head/sys/netinet/udp_usrreq.c
> head/sys/sys/malloc.h
>
> Modified: head/sys/netinet/ip_divert.c
>
> ==
> --- head/sys/netinet/ip_divert.cMon Jul 2 01:30:33 2018
> (r335855)
> +++ head/sys/netinet/ip_divert.cMon Jul 2 05:19:44 2018
> (r335856)
> @@ -552,7 +552,6 @@ div_detach(struct socket *so)
> KASSERT(inp != NULL, ("div_detach: inp == NULL"));
> INP_INFO_WLOCK(_divcbinfo);
> INP_WLOCK(inp);
> - /* XXX defer destruction to epoch_call */
> in_pcbdetach(inp);
> in_pcbfree(inp);
> INP_INFO_WUNLOCK(_divcbinfo);
> @@ -632,7 +631,6 @@ static int
> div_pcblist(SYSCTL_HANDLER_ARGS)
> {
> int error, i, n;
> - struct in_pcblist *il;
> struct inpcb *inp, **inp_list;
> inp_gen_t gencnt;
> struct xinpgen xig;
> @@ -672,8 +670,9 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
> if (error)
> return error;
>
> - il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb
> *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
> - inp_list = il->il_inp_list;
> + inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
> + if (inp_list == NULL)
> + return ENOMEM;
>
> INP_INFO_RLOCK(_divcbinfo);
> for (inp = CK_LIST_FIRST(V_divcbinfo.ipi_listhead), i = 0; inp &&
> i < n;
> @@ -702,9 +701,14 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
> } else
> INP_RUNLOCK(inp);
> }
> - il->il_count = n;
> - il->il_pcbinfo = _divcbinfo;
> - epoch_call(net_epoch_preempt, >il_epoch_ctx,
> in_pcblist_rele_rlocked);
> + INP_INFO_WLOCK(_divcbinfo);
> + for (i = 0; i < n; i++) {
> + inp = inp_list[i];
> + INP_RLOCK(inp);
> + if (!in_pcbrele_rlocked(inp))
> + INP_RUNLOCK(inp);
> + }
> + INP_INFO_WUNLOCK(_divcbinfo);
>
> if (!error) {
> /*
> @@ -721,6 +725,7 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
> INP_INFO_RUNLOCK(_divcbinfo);
> error = SYSCTL_OUT(req, , sizeof xig);
> }
> + free(inp_list, M_TEMP);
> return error;
> }
>
> @@ -800,7 +805,6 @@ div_modevent(module_t mod, int type, void *unused)
> break;
> }
> ip_divert_ptr = NULL;
> - /* XXX defer to epoch_call ? */
> err = pf_proto_unregister(PF_INET, IPPROTO_DIVERT,
> SOCK_RAW);
> INP_INFO_WUNLOCK(_divcbinfo);
> #ifndef VIMAGE
>
> Modified: head/sys/netinet/raw_ip.c
>
> ==
> --- head/sys/netinet/raw_ip.c Mon Jul 2 01:30:33 2018(r335855)
> +++ head/sys/netinet/raw_ip.c Mon Jul 2 05:19:44 2018(r335856)
> @@ -863,7 +863,6 @@ rip_detach(struct socket *so)
> ip_rsvp_force_done(so);
> if (so == V_ip_rsvpd)
> ip_rsvp_done();
> - /* XXX defer to epoch_call */
> in_pcbdetach(inp);
> in_pcbfree(inp);
> INP_INFO_WUNLOCK(_ripcbinfo);
> @@ -1033,7 +1032,6 @@ static int
> rip_pcblist(SYSCTL_HANDLER_ARGS)
> {
> int error, i, n;
> - struct in_pcblist *il;
> struct inpcb *inp, **inp_list;
> inp_gen_t gencnt;
> struct xinpgen xig;
> @@ -1068,8 +1066,9 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
> if (error)
> return (error);
>
> - il = malloc(sizeof(struct in_pcblist) + n * sizeof(struct inpcb
> *), M_TEMP, M_WAITOK|M_ZERO_INVARIANTS);
> - inp_list = il->il_inp_list;
> + inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
> + if (inp_list == NULL)
> + return (ENOMEM);
>
> INP_INFO_RLOCK(_ripcbinfo);
> for (inp = CK_LIST_FIRST(V_ripcbinfo.ipi_listhead), i = 0; inp &&
> i < n;
> @@ -1098,9 +1097,14 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
> } else
> INP_RUNLOCK(inp);
> }
> - il->il_count = n;
> - il->il_pcbinfo = _ripcbinfo;
> - epoch_call(net_epoch_preempt, >il_epoch_ctx,
> in_pcblist_rele_rlocked);
> + INP_INFO_WLOCK(_ripcbinfo);
> + for (i = 0; i < n; i++) {
> + inp = inp_list[i];
> + INP_RLOCK(inp);
> + if