Introduce PR_MPSYSCTL flag to mark mp-safe (*pr_sysctl)() handlers and
authormvs <mvs@openbsd.org>
Fri, 16 Aug 2024 09:20:34 +0000 (09:20 +0000)
committermvs <mvs@openbsd.org>
Fri, 16 Aug 2024 09:20:34 +0000 (09:20 +0000)
unlock both divert_sysctl() and divert6_sysctl(). Unlock them together,
because they are identical and pretty simple:

- DIVERTCTL_RECVSPACE and DIVERTCTL_SENDSPACE - atomically accessed
  integers;
- DIVERTCTL_STATS - per-CPU counters;

ok bluhm

sys/kern/uipc_domain.c
sys/netinet/in_proto.c
sys/netinet/ip_divert.c
sys/netinet6/in6_proto.c
sys/netinet6/ip6_divert.c
sys/sys/protosw.h

index 1c31480..4e7a54d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_domain.c,v 1.67 2024/08/14 17:52:47 mvs Exp $    */
+/*     $OpenBSD: uipc_domain.c,v 1.68 2024/08/16 09:20:34 mvs Exp $    */
 /*     $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $        */
 
 /*
@@ -237,14 +237,18 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        protocol = name[1];
        for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
                if (pr->pr_protocol == protocol && pr->pr_sysctl) {
-                       size_t savelen = *oldlenp;
+                       size_t savelen;
                        int error;
 
-                       if ((error = sysctl_vslock(oldp, savelen)))
-                               return (error);
+                       if ((pr->pr_flags & PR_MPSYSCTL) == 0) {
+                               savelen = *oldlenp;
+                               if ((error = sysctl_vslock(oldp, savelen)))
+                                       return (error);
+                       }
                        error = (*pr->pr_sysctl)(name + 2, namelen - 2,
                            oldp, oldlenp, newp, newlen);
-                       sysctl_vsunlock(oldp, savelen);
+                       if ((pr->pr_flags & PR_MPSYSCTL) == 0)
+                               sysctl_vsunlock(oldp, savelen);
 
                        return (error);
                }
index 579522f..a279775 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_proto.c,v 1.107 2024/07/26 14:38:20 bluhm Exp $    */
+/*     $OpenBSD: in_proto.c,v 1.108 2024/08/16 09:20:35 mvs Exp $      */
 /*     $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $   */
 
 /*
@@ -354,7 +354,7 @@ const struct protosw inetsw[] = {
   .pr_type     = SOCK_RAW,
   .pr_domain   = &inetdomain,
   .pr_protocol = IPPROTO_DIVERT,
-  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_ctloutput        = rip_ctloutput,
   .pr_usrreqs  = &divert_usrreqs,
   .pr_init     = divert_init,
index 260d23c..21157d2 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip_divert.c,v 1.96 2024/07/12 19:50:35 bluhm Exp $ */
+/*      $OpenBSD: ip_divert.c,v 1.97 2024/08/16 09:20:35 mvs Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
 
 #include <net/pfvar.h>
 
+/*
+ * Locks used to protect data:
+ *     a       atomic
+ */
+
 struct inpcbtable      divbtable;
 struct cpumem          *divcounters;
 
 #ifndef DIVERT_SENDSPACE
 #define DIVERT_SENDSPACE       (65536 + 100)
 #endif
-u_int   divert_sendspace = DIVERT_SENDSPACE;
+u_int   divert_sendspace = DIVERT_SENDSPACE;   /* [a] */
 #ifndef DIVERT_RECVSPACE
 #define DIVERT_RECVSPACE       (65536 + 100)
 #endif
-u_int   divert_recvspace = DIVERT_RECVSPACE;
+u_int   divert_recvspace = DIVERT_RECVSPACE;   /* [a] */
 
 #ifndef DIVERTHASHSIZE
 #define DIVERTHASHSIZE 128
@@ -271,7 +276,8 @@ divert_attach(struct socket *so, int proto, int wait)
        if (error)
                return error;
 
-       error = soreserve(so, divert_sendspace, divert_recvspace);
+       error = soreserve(so, atomic_load_int(&divert_sendspace),
+           atomic_load_int(&divert_recvspace));
        if (error)
                return error;
 
@@ -346,8 +352,6 @@ int
 divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen)
 {
-       int error;
-
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -356,12 +360,9 @@ divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        case DIVERTCTL_STATS:
                return (divert_sysctl_divstat(oldp, oldlenp, newp));
        default:
-               NET_LOCK();
-               error = sysctl_bounded_arr(divertctl_vars,
-                   nitems(divertctl_vars), name, namelen, oldp, oldlenp, newp,
-                   newlen);
-               NET_UNLOCK();
-               return (error);
+               return (sysctl_bounded_arr(divertctl_vars,
+                   nitems(divertctl_vars), name, namelen, oldp, oldlenp,
+                   newp, newlen));
        }
        /* NOTREACHED */
 }
index 2d7343a..d35cff4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6_proto.c,v 1.117 2024/07/26 14:38:20 bluhm Exp $   */
+/*     $OpenBSD: in6_proto.c,v 1.118 2024/08/16 09:20:35 mvs Exp $     */
 /*     $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $      */
 
 /*
@@ -289,7 +289,7 @@ const struct protosw inet6sw[] = {
   .pr_type     = SOCK_RAW,
   .pr_domain   = &inet6domain,
   .pr_protocol = IPPROTO_DIVERT,
-  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_ctloutput        = rip6_ctloutput,
   .pr_usrreqs  = &divert6_usrreqs,
   .pr_init     = divert6_init,
index 06111f6..dc815d5 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip6_divert.c,v 1.96 2024/07/12 19:50:35 bluhm Exp $ */
+/*      $OpenBSD: ip6_divert.c,v 1.97 2024/08/16 09:20:35 mvs Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
 
 #include <net/pfvar.h>
 
+/*
+ * Locks used to protect data:
+ *     a       atomic
+ */
+
 struct inpcbtable      divb6table;
 struct cpumem          *div6counters;
 
 #ifndef DIVERT_SENDSPACE
 #define DIVERT_SENDSPACE       (65536 + 100)
 #endif
-u_int   divert6_sendspace = DIVERT_SENDSPACE;
+u_int   divert6_sendspace = DIVERT_SENDSPACE;  /* [a] */
 #ifndef DIVERT_RECVSPACE
 #define DIVERT_RECVSPACE       (65536 + 100)
 #endif
-u_int   divert6_recvspace = DIVERT_RECVSPACE;
+u_int   divert6_recvspace = DIVERT_RECVSPACE;  /* [a] */
 
 #ifndef DIVERTHASHSIZE
 #define DIVERTHASHSIZE 128
@@ -279,7 +284,8 @@ divert6_attach(struct socket *so, int proto, int wait)
        if (error)
                return (error);
 
-       error = soreserve(so, divert6_sendspace, divert6_recvspace);
+       error = soreserve(so, atomic_load_int(&divert6_sendspace),
+           atomic_load_int(&divert6_recvspace));
        if (error)
                return (error);
 
@@ -322,8 +328,6 @@ int
 divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
     void *newp, size_t newlen)
 {
-       int error;
-
        /* All sysctl names at this level are terminal. */
        if (namelen != 1)
                return (ENOTDIR);
@@ -332,12 +336,9 @@ divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
        case DIVERT6CTL_STATS:
                return (divert6_sysctl_div6stat(oldp, oldlenp, newp));
        default:
-               NET_LOCK();
-               error = sysctl_bounded_arr(divert6ctl_vars,
+               return (sysctl_bounded_arr(divert6ctl_vars,
                    nitems(divert6ctl_vars), name, namelen, oldp, oldlenp,
-                   newp, newlen);
-               NET_UNLOCK();
-               return (error);
+                   newp, newlen));
        }
        /* NOTREACHED */
 }
index 575fdbd..6aa88ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: protosw.h,v 1.67 2024/07/12 19:50:35 bluhm Exp $      */
+/*     $OpenBSD: protosw.h,v 1.68 2024/08/16 09:20:35 mvs Exp $        */
 /*     $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */
 
 /*-
@@ -131,6 +131,7 @@ struct protosw {
 #define PR_SPLICE      0x0040          /* socket splicing is possible */
 #define PR_MPINPUT     0x0080          /* input runs with shared netlock */
 #define PR_MPSOCKET    0x0100          /* socket uses shared netlock */
+#define PR_MPSYSCTL    0x0200          /* mp-safe sysctl(2) handler */
 
 /*
  * The arguments to usrreq are: