I'd like to reduce the number of blocking memory allocations holding
the NET_LOCK().

Diff below moves m_get(M_WAIT) before grabbing the socket lock for
sogetopt().

ok?

Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.201
diff -u -p -r1.201 uipc_socket.c
--- kern/uipc_socket.c  10 Aug 2017 19:20:43 -0000      1.201
+++ kern/uipc_socket.c  21 Aug 2017 13:22:27 -0000
@@ -1755,30 +1755,24 @@ bad:
 }
 
 int
-sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
+sogetopt(struct socket *so, int level, int optname, struct mbuf *m)
 {
        int error = 0;
-       struct mbuf *m;
 
        soassertlocked(so);
 
        if (level != SOL_SOCKET) {
                if (so->so_proto->pr_ctloutput) {
-                       m = m_get(M_WAIT, MT_SOOPTS);
                        m->m_len = 0;
 
                        error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT, so,
                            level, optname, m);
-                       if (error) {
-                               m_free(m);
+                       if (error)
                                return (error);
-                       }
-                       *mp = m;
                        return (0);
                } else
                        return (ENOPROTOOPT);
        } else {
-               m = m_get(M_WAIT, MT_SOOPTS);
                m->m_len = sizeof (int);
 
                switch (optname) {
@@ -1856,13 +1850,10 @@ sogetopt(struct socket *so, int level, i
                                level = dom->dom_protosw->pr_protocol;
                                error = (*so->so_proto->pr_ctloutput)
                                    (PRCO_GETOPT, so, level, optname, m);
-                               if (error) {
-                                       (void)m_free(m);
+                               if (error)
                                        return (error);
-                               }
                                break;
                        }
-                       (void)m_free(m);
                        return (ENOPROTOOPT);
 
 #ifdef SOCKET_SPLICE
@@ -1887,17 +1878,13 @@ sogetopt(struct socket *so, int level, i
                                            &(unp->unp_connid), m->m_len);
                                        break;
                                }
-                               (void)m_free(m);
                                return (ENOTCONN);
                        }
-                       (void)m_free(m);
                        return (EOPNOTSUPP);
 
                default:
-                       (void)m_free(m);
                        return (ENOPROTOOPT);
                }
-               *mp = m;
                return (0);
        }
 }
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.158
diff -u -p -r1.158 uipc_syscalls.c
--- kern/uipc_syscalls.c        10 Aug 2017 19:20:43 -0000      1.158
+++ kern/uipc_syscalls.c        21 Aug 2017 13:17:17 -0000
@@ -1014,9 +1014,10 @@ sys_getsockopt(struct proc *p, void *v, 
                        goto out;
        } else
                valsize = 0;
+       m = m_get(M_WAIT, MT_SOOPTS);
        so = fp->f_data;
        s = solock(so);
-       error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), &m);
+       error = sogetopt(so, SCARG(uap, level), SCARG(uap, name), m);
        sounlock(s);
        if (error == 0 && SCARG(uap, val) && valsize && m != NULL) {
                if (valsize > m->m_len)
@@ -1026,9 +1027,9 @@ sys_getsockopt(struct proc *p, void *v, 
                        error = copyout(&valsize,
                            SCARG(uap, avalsize), sizeof (valsize));
        }
+       m_free(m);
 out:
        FRELE(fp, p);
-       m_free(m);
        return (error);
 }
 

Reply via email to