Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netcan Don't kmem_alloc()/kmem_free() with spin lock hel...



details:   https://anonhg.NetBSD.org/src/rev/9911c9d6472b
branches:  trunk
changeset: 461951:9911c9d6472b
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Jul 20 15:34:41 2019 +0000

description:
Don't kmem_alloc()/kmem_free() with spin lock held: call can_pcbsetfilter()
without canp_mtx; take it here and check canp_state before updating the
canp_filters.

diffstat:

 sys/netcan/can.c     |   6 ++----
 sys/netcan/can_pcb.c |  33 +++++++++++++++++++++++----------
 2 files changed, 25 insertions(+), 14 deletions(-)

diffs (98 lines):

diff -r f6a418bc9714 -r 9911c9d6472b sys/netcan/can.c
--- a/sys/netcan/can.c  Sat Jul 20 13:29:36 2019 +0000
+++ b/sys/netcan/can.c  Sat Jul 20 15:34:41 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: can.c,v 1.6 2018/11/15 10:23:56 maxv Exp $     */
+/*     $NetBSD: can.c,v 1.7 2019/07/20 15:34:41 bouyer Exp $   */
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.6 2018/11/15 10:23:56 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.7 2019/07/20 15:34:41 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -924,9 +924,7 @@
                int nfilters = sopt->sopt_size / sizeof(struct can_filter);
                if (sopt->sopt_size % sizeof(struct can_filter) != 0)
                        return EINVAL;
-               mutex_enter(&canp->canp_mtx);
                error = can_pcbsetfilter(canp, sopt->sopt_data, nfilters);
-               mutex_exit(&canp->canp_mtx);
                break;
                }
        default:
diff -r f6a418bc9714 -r 9911c9d6472b sys/netcan/can_pcb.c
--- a/sys/netcan/can_pcb.c      Sat Jul 20 13:29:36 2019 +0000
+++ b/sys/netcan/can_pcb.c      Sat Jul 20 15:34:41 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: can_pcb.c,v 1.7 2019/02/25 06:49:44 maxv Exp $ */
+/*     $NetBSD: can_pcb.c,v 1.8 2019/07/20 15:34:41 bouyer Exp $       */
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can_pcb.c,v 1.7 2019/02/25 06:49:44 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can_pcb.c,v 1.8 2019/07/20 15:34:41 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -193,8 +193,8 @@
        so->so_pcb = NULL;
        mutex_enter(&canp->canp_mtx);
        can_pcbstate(canp, CANP_DETACHED);
+       mutex_exit(&canp->canp_mtx);
        can_pcbsetfilter(canp, NULL, 0);
-       mutex_exit(&canp->canp_mtx);
        TAILQ_REMOVE(&canp->canp_table->canpt_queue, canp, canp_queue);
        sofree(so); /* sofree drops the softnet_lock */
        canp_unref(canp);
@@ -243,7 +243,9 @@
 {
 
        struct can_filter *newf;
-       KASSERT(mutex_owned(&canp->canp_mtx));
+       struct can_filter *oldf;
+       int oldnf;
+       int error = 0;
 
        if (nfilters > 0) {
                newf =
@@ -252,13 +254,24 @@
        } else {
                newf = NULL;
        }
-       if (canp->canp_filters != NULL) {
-               kmem_free(canp->canp_filters,
-                   sizeof(struct can_filter) * canp->canp_nfilters);
+       mutex_enter(&canp->canp_mtx);
+       oldf = canp->canp_filters;
+       oldnf = canp->canp_nfilters;
+       if (newf != NULL && canp->canp_state == CANP_DETACHED) {
+               error = ECONNRESET;
+       } else {
+               canp->canp_filters = newf;
+               canp->canp_nfilters = nfilters;
+               newf = NULL;
        }
-       canp->canp_filters = newf;
-       canp->canp_nfilters = nfilters;
-       return 0;
+       mutex_exit(&canp->canp_mtx);
+       if (oldf != NULL) {
+               kmem_free(oldf, sizeof(struct can_filter) * oldnf);
+       }
+       if (newf != NULL) {
+               kmem_free(newf, sizeof(struct can_filter) * nfilters);
+       }
+       return error;
 }
 
 



Home | Main Index | Thread Index | Old Index