Author: melifaro
Date: Mon May 21 22:19:19 2012
New Revision: 235746
URL: http://svn.freebsd.org/changeset/base/235746

Log:
  Call bpf_jitter() before acquiring BPF global lock due to malloc() being used 
inside bpf_jitter.
  
  Eliminate bpf_buffer_alloc() and allocate BPF buffers on descriptor creation 
and BIOCSBLEN ioctl.
  This permits us not to allocate buffers inside bpf_attachd() which is 
protected by global lock.
  
  Approved by:      kib(mentor)
  MFC in:            4 weeks

Modified:
  head/sys/net/bpf.c
  head/sys/net/bpf_buffer.c
  head/sys/net/bpf_buffer.h

Modified: head/sys/net/bpf.c
==============================================================================
--- head/sys/net/bpf.c  Mon May 21 22:17:29 2012        (r235745)
+++ head/sys/net/bpf.c  Mon May 21 22:19:19 2012        (r235746)
@@ -804,7 +804,7 @@ static      int
 bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
 {
        struct bpf_d *d;
-       int error;
+       int error, size;
 
        d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
        error = devfs_set_cdevpriv(d, bpf_dtor);
@@ -831,6 +831,10 @@ bpfopen(struct cdev *dev, int flags, int
        callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
        knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
 
+       /* Allocate default buffers */
+       size = d->bd_bufsize;
+       bpf_buffer_ioctl_sblen(d, &size);
+
        return (0);
 }
 
@@ -1664,7 +1668,7 @@ bpf_setf(struct bpf_d *d, struct bpf_pro
        struct bpf_insn *fcode, *old;
        u_int wfilter, flen, size;
 #ifdef BPF_JITTER
-       bpf_jit_filter *ofunc;
+       bpf_jit_filter *ofunc, *jfunc;
 #endif
        int need_upgrade;
 #ifdef COMPAT_FREEBSD32
@@ -1695,6 +1699,13 @@ bpf_setf(struct bpf_d *d, struct bpf_pro
        else
                fcode = NULL; /* Make compiler happy */
 
+#ifdef BPF_JITTER
+       if (fp->bf_insns != NULL)
+               jfunc = bpf_jitter(fcode, flen);
+       else
+               jfunc = NULL; /* Make compiler happy */
+#endif
+
        BPF_LOCK();
 
        if (cmd == BIOCSETWF) {
@@ -1755,7 +1766,7 @@ bpf_setf(struct bpf_d *d, struct bpf_pro
                else {
                        d->bd_rfilter = fcode;
 #ifdef BPF_JITTER
-                       d->bd_bfilter = bpf_jitter(fcode, flen);
+                       d->bd_bfilter = jfunc;
 #endif
                        if (cmd == BIOCSETF)
                                reset_d(d);
@@ -1827,11 +1838,6 @@ bpf_setif(struct bpf_d *d, struct ifreq 
         */
        switch (d->bd_bufmode) {
        case BPF_BUFMODE_BUFFER:
-               if (d->bd_sbuf == NULL)
-                       bpf_buffer_alloc(d);
-               KASSERT(d->bd_sbuf != NULL, ("bpf_setif: bd_sbuf NULL"));
-               break;
-
        case BPF_BUFMODE_ZBUF:
                if (d->bd_sbuf == NULL)
                        return (EINVAL);

Modified: head/sys/net/bpf_buffer.c
==============================================================================
--- head/sys/net/bpf_buffer.c   Mon May 21 22:17:29 2012        (r235745)
+++ head/sys/net/bpf_buffer.c   Mon May 21 22:19:19 2012        (r235746)
@@ -93,21 +93,6 @@ static int bpf_maxbufsize = BPF_MAXBUFSI
 SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
     &bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
 
-void
-bpf_buffer_alloc(struct bpf_d *d)
-{
-
-       KASSERT(d->bd_fbuf == NULL, ("bpf_buffer_alloc: bd_fbuf != NULL"));
-       KASSERT(d->bd_sbuf == NULL, ("bpf_buffer_alloc: bd_sbuf != NULL"));
-       KASSERT(d->bd_hbuf == NULL, ("bpf_buffer_alloc: bd_hbuf != NULL"));
-
-       d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
-       d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_BPF, M_WAITOK);
-       d->bd_hbuf = NULL;
-       d->bd_slen = 0;
-       d->bd_hlen = 0;
-}
-
 /*
  * Simple data copy to the current kernel buffer.
  */
@@ -183,18 +168,42 @@ int
 bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
 {
        u_int size;
+       caddr_t fbuf, sbuf;
 
-       BPFD_LOCK(d);
-       if (d->bd_bif != NULL) {
-               BPFD_UNLOCK(d);
-               return (EINVAL);
-       }
        size = *i;
        if (size > bpf_maxbufsize)
                *i = size = bpf_maxbufsize;
        else if (size < BPF_MINBUFSIZE)
                *i = size = BPF_MINBUFSIZE;
+
+       /* Allocate buffers immediately */
+       fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+       sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
+
+       BPFD_LOCK(d);
+       if (d->bd_bif != NULL) {
+               /* Interface already attached, unable to change buffers */
+               BPFD_UNLOCK(d);
+               free(fbuf, M_BPF);
+               free(sbuf, M_BPF);
+               return (EINVAL);
+       }
+
+       /* Free old buffers if set */
+       if (d->bd_fbuf != NULL)
+               free(d->bd_fbuf, M_BPF);
+       if (d->bd_sbuf != NULL)
+               free(d->bd_sbuf, M_BPF);
+
+       /* Fill in new data */
        d->bd_bufsize = size;
+       d->bd_fbuf = fbuf;
+       d->bd_sbuf = sbuf;
+
+       d->bd_hbuf = NULL;
+       d->bd_slen = 0;
+       d->bd_hlen = 0;
+
        BPFD_UNLOCK(d);
        return (0);
 }

Modified: head/sys/net/bpf_buffer.h
==============================================================================
--- head/sys/net/bpf_buffer.h   Mon May 21 22:17:29 2012        (r235745)
+++ head/sys/net/bpf_buffer.h   Mon May 21 22:19:19 2012        (r235746)
@@ -36,7 +36,6 @@
 #error "no user-serviceable parts inside"
 #endif
 
-void   bpf_buffer_alloc(struct bpf_d *d);
 void   bpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
            void *src, u_int len);
 void   bpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset,
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to