On Fri, Jul 10, 2020 at 10:45:54AM +0200, Martin Pieuchot wrote:
> On 08/07/20(Wed) 12:05, Vitaliy Makkoveev wrote:
> > `pppx_devs_lk' used to protect `pxd_entry' list. We lock `pppx_devs_lk'
> > in pppx_if_output() to be sure `pxd' is not destroyed by concurrent
> > pppxclose() but it's useless. We destroy all corresponding `pxi' before
> > `pxd' and `ifnet's are already detached.
> 
> This lock seems to only prevent races if malloc(9) sleeps inside
> pppxopen().  Could you address that and remove the lock altogether?
> 
> What is really protecting the data structure and lifetime of its
> elements is the KERNEL_LOCK() currently.

Updated diff which removes `pppx_devs_lk'.

Index: sys/net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.91
diff -u -p -r1.91 if_pppx.c
--- sys/net/if_pppx.c   6 Jul 2020 20:37:51 -0000       1.91
+++ sys/net/if_pppx.c   10 Jul 2020 09:49:11 -0000
@@ -50,7 +50,6 @@
 #include <sys/device.h>
 #include <sys/conf.h>
 #include <sys/queue.h>
-#include <sys/rwlock.h>
 #include <sys/pool.h>
 #include <sys/mbuf.h>
 #include <sys/errno.h>
@@ -132,9 +131,8 @@ struct pppx_dev {
        LIST_HEAD(,pppx_if)     pxd_pxis;
 };
 
-struct rwlock                  pppx_devs_lk = RWLOCK_INITIALIZER("pppxdevs");
 LIST_HEAD(, pppx_dev)          pppx_devs = LIST_HEAD_INITIALIZER(pppx_devs);
-struct pool                    *pppx_if_pl;
+struct pool                    pppx_if_pl;
 
 struct pppx_dev                        *pppx_dev_lookup(dev_t);
 struct pppx_dev                        *pppx_dev2pxd(dev_t);
@@ -218,8 +216,6 @@ pppx_dev_lookup(dev_t dev)
        struct pppx_dev *pxd;
        int unit = minor(dev);
 
-       /* must hold pppx_devs_lk */
-
        LIST_FOREACH(pxd, &pppx_devs, pxd_entry) {
                if (pxd->pxd_unit == unit)
                        return (pxd);
@@ -233,9 +229,7 @@ pppx_dev2pxd(dev_t dev)
 {
        struct pppx_dev *pxd;
 
-       rw_enter_read(&pppx_devs_lk);
        pxd = pppx_dev_lookup(dev);
-       rw_exit_read(&pppx_devs_lk);
 
        return (pxd);
 }
@@ -243,6 +237,8 @@ pppx_dev2pxd(dev_t dev)
 void
 pppxattach(int n)
 {
+       pool_init(&pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE,
+           PR_WAITOK, "pppxif", NULL);
        pipex_init();
 }
 
@@ -250,25 +246,12 @@ int
 pppxopen(dev_t dev, int flags, int mode, struct proc *p)
 {
        struct pppx_dev *pxd;
-       int rv = 0;
-
-       rv = rw_enter(&pppx_devs_lk, RW_WRITE | RW_INTR);
-       if (rv != 0)
-               return (rv);
-
-       pxd = pppx_dev_lookup(dev);
-       if (pxd != NULL) {
-               rv = EBUSY;
-               goto out;
-       }
-
-       if (LIST_EMPTY(&pppx_devs) && pppx_if_pl == NULL) {
-               pppx_if_pl = malloc(sizeof(*pppx_if_pl), M_DEVBUF, M_WAITOK);
-               pool_init(pppx_if_pl, sizeof(struct pppx_if), 0, IPL_NONE,
-                   PR_WAITOK, "pppxif", NULL);
-       }
 
        pxd = malloc(sizeof(*pxd), M_DEVBUF, M_WAITOK | M_ZERO);
+       if (pppx_dev_lookup(dev) != NULL) {
+               free(pxd, M_DEVBUF, sizeof(*pxd));
+               return (EBUSY);
+       }
 
        pxd->pxd_unit = minor(dev);
        mtx_init(&pxd->pxd_rsel_mtx, IPL_NET);
@@ -278,9 +261,7 @@ pppxopen(dev_t dev, int flags, int mode,
        mq_init(&pxd->pxd_svcq, 128, IPL_NET);
        LIST_INSERT_HEAD(&pppx_devs, pxd, pxd_entry);
 
-out:
-       rw_exit(&pppx_devs_lk);
-       return (rv);
+       return 0;
 }
 
 int
@@ -587,8 +568,6 @@ pppxclose(dev_t dev, int flags, int mode
        struct pppx_dev *pxd;
        struct pppx_if  *pxi;
 
-       rw_enter_write(&pppx_devs_lk);
-
        pxd = pppx_dev_lookup(dev);
 
        /* XXX */
@@ -603,13 +582,6 @@ pppxclose(dev_t dev, int flags, int mode
 
        free(pxd, M_DEVBUF, sizeof(*pxd));
 
-       if (LIST_EMPTY(&pppx_devs)) {
-               pool_destroy(pppx_if_pl);
-               free(pppx_if_pl, M_DEVBUF, sizeof(*pppx_if_pl));
-               pppx_if_pl = NULL;
-       }
-
-       rw_exit_write(&pppx_devs_lk);
        return (0);
 }
 
@@ -676,7 +648,7 @@ pppx_add_session(struct pppx_dev *pxd, s
        if (error)
                return (error);
 
-       pxi = pool_get(pppx_if_pl, PR_WAITOK | PR_ZERO);
+       pxi = pool_get(&pppx_if_pl, PR_WAITOK | PR_ZERO);
        ifp = &pxi->pxi_if;
 
        pxi->pxi_session = session;
@@ -776,7 +748,7 @@ remove:
                panic("%s: inconsistent RB tree", __func__);
        LIST_REMOVE(pxi, pxi_list);
 out:
-       pool_put(pppx_if_pl, pxi);
+       pool_put(&pppx_if_pl, pxi);
        pipex_rele_session(session);
 
        return (error);
@@ -871,7 +843,7 @@ pppx_if_destroy(struct pppx_dev *pxd, st
                panic("%s: inconsistent RB tree", __func__);
        LIST_REMOVE(pxi, pxi_list);
 
-       pool_put(pppx_if_pl, pxi);
+       pool_put(&pppx_if_pl, pxi);
 }
 
 void
@@ -957,7 +929,6 @@ pppx_if_output(struct ifnet *ifp, struct
                th = mtod(m, struct pppx_hdr *);
                th->pppx_proto = 0;     /* not used */
                th->pppx_id = pxi->pxi_session->ppp_id;
-               rw_enter_read(&pppx_devs_lk);
                error = mq_enqueue(&pxi->pxi_dev->pxd_svcq, m);
                if (error == 0) {
                        if (pxi->pxi_dev->pxd_waiting) {
@@ -966,7 +937,6 @@ pppx_if_output(struct ifnet *ifp, struct
                        }
                        selwakeup(&pxi->pxi_dev->pxd_rsel);
                }
-               rw_exit_read(&pppx_devs_lk);
        }
 
 out:

Reply via email to