Index: bpf.c =================================================================== RCS file: /cvs/src/sys/net/bpf.c,v retrieving revision 1.109 diff -u -p -r1.109 bpf.c --- bpf.c 23 Sep 2014 00:26:11 -0000 1.109 +++ bpf.c 23 Sep 2014 07:35:03 -0000 @@ -85,6 +85,7 @@ int bpf_maxbufsize = BPF_MAXBUFSIZE; */ struct bpf_if *bpf_iflist; LIST_HEAD(, bpf_d) bpf_d_list; +struct rwlock bpf_d_lock; void bpf_allocbufs(struct bpf_d *); void bpf_freed(struct bpf_d *); @@ -310,6 +311,7 @@ void bpfilterattach(int n) { LIST_INIT(&bpf_d_list); + rw_init(&bpf_d_lock, "bpfd"); } /* @@ -1515,12 +1517,17 @@ bpfdetach(struct ifnet *ifp) * Locate the minor number and nuke the vnode * for any open instance. */ - LIST_FOREACH(d, &bpf_d_list, bd_list) - if (d == bd) { - vdevgone(maj, d->bd_unit, - d->bd_unit, VCHR); + rw_enter_read(&bpf_d_lock); + LIST_FOREACH(d, &bpf_d_list, bd_list) { + if (d == bd) break; - } + } + rw_exit_read(&bpf_d_lock); + + if (d != NULL) { + vdevgone(maj, d->bd_unit, + d->bd_unit, VCHR); + } } free(bp, M_DEVBUF, 0); @@ -1591,10 +1598,14 @@ bpfilter_lookup(int unit) { struct bpf_d *bd; - LIST_FOREACH(bd, &bpf_d_list, bd_list) + rw_enter_read(&bpf_d_lock); + LIST_FOREACH(bd, &bpf_d_list, bd_list) { if (bd->bd_unit == unit) - return (bd); - return (NULL); + break; + } + rw_exit_read(&bpf_d_lock); + + return (bd); } struct bpf_d * @@ -1602,19 +1613,37 @@ bpfilter_create(int unit) { struct bpf_d *bd; - if ((bd = bpfilter_lookup(unit)) != NULL) - return (NULL); - if ((bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT|M_ZERO)) != NULL) { - bd->bd_unit = unit; - LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list); + rw_enter_write(&bpf_d_lock); + + LIST_FOREACH(bd, &bpf_d_list, bd_list) { + if (bd->bd_unit == unit) + break; + } + + if (bd != NULL) { + bd = NULL; + goto out; } + + bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT|M_ZERO); + if (bd == NULL) + goto out; + + bd->bd_unit = unit; + LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list); + +out: + rw_exit_write(&bpf_d_lock); return (bd); } void bpfilter_destroy(struct bpf_d *bd) { + rw_enter_write(&bpf_d_lock); LIST_REMOVE(bd, bd_list); + rw_exit_write(&bpf_d_lock); + free(bd, M_DEVBUF, 0); }