On Thu, Dec 10, 2020 at 11:26:16AM -0600, Scott Cheloha wrote:
> Hi,
> 
> Before converting bpf(4) from using ticks to using real units of time
> we need to serialize BIOCGRTIMEOUT and BIOCSRTIMEOUT.  Neither
> operation is atomic so we need to use the per-descriptor mutex when
> reading or writing the bd_rtout member.
> 
> While here we can start annotating the locking for struct members in
> bpfdesc.h, too.
> 
> ok?
> Index: bpf.c
> ===================================================================
> RCS file: /cvs/src/sys/net/bpf.c,v
> retrieving revision 1.193
> diff -u -p -r1.193 bpf.c
> --- bpf.c     4 Nov 2020 04:40:13 -0000       1.193
> +++ bpf.c     10 Dec 2020 17:24:43 -0000
> @@ -873,9 +873,11 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t 
>                               break;
>                       }
>                       rtout += tv->tv_usec / tick;
> +                     mtx_enter(&d->bd_mtx);
>                       d->bd_rtout = rtout;
>                       if (d->bd_rtout == 0 && tv->tv_usec != 0)
>                               d->bd_rtout = 1;

This code could be refactored to write bd_rtout only once.
                        if (rtout == 0 && tv->tv_usec != 0)
                                rtout = 1;
                        d->bd_rtout = rtout;
or using WRITE_ONCE
                        WRITE_ONCE(d->bd_rtout, rtout);

This way the mutex would no longer be required since this is an atomic
update.

> +                     mtx_leave(&d->bd_mtx);
>                       break;
>               }
>  
> @@ -886,8 +888,10 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t 
>               {
>                       struct timeval *tv = (struct timeval *)addr;
>  
> +                     mtx_enter(&d->bd_mtx);
>                       tv->tv_sec = d->bd_rtout / hz;
>                       tv->tv_usec = (d->bd_rtout % hz) * tick;

Same here using a local rtout variable:
                        rtout = READ_ONCE(d->bd_rtout);
                        tv->tv_sec = rtout / hz;
                        tv->tv_usec = (rtout % hz) * tick;

Again this would be an atomic operation and the lock would not be needed
anymore.

I guess moving forward bd_rtout will be changed since it is tick based so
maybe then the update can no longer be made in an atomic fashion.

> +                     mtx_leave(&d->bd_mtx);
>                       break;
>               }
>  
> Index: bpfdesc.h
> ===================================================================
> RCS file: /cvs/src/sys/net/bpfdesc.h,v
> retrieving revision 1.41
> diff -u -p -r1.41 bpfdesc.h
> --- bpfdesc.h 13 May 2020 21:34:37 -0000      1.41
> +++ bpfdesc.h 10 Dec 2020 17:24:43 -0000
> @@ -42,6 +42,13 @@
>  
>  #ifdef _KERNEL
>  
> +/*
> + * Locks used to protect struct members in this file:
> + *
> + *   I       immutable after initialization
> + *   m       the per-descriptor mutex (bpf_d.bd_mtx)
> + */
> +
>  struct bpf_program_smr {
>       struct bpf_program      bps_bf;
>       struct smr_entry        bps_smr;
> @@ -72,7 +79,7 @@ struct bpf_d {
>       int             bd_in_uiomove;  /* for debugging purpose */
>  
>       struct bpf_if  *bd_bif;         /* interface descriptor */
> -     u_long          bd_rtout;       /* Read timeout in 'ticks' */
> +     u_long          bd_rtout;       /* [m] Read timeout in 'ticks' */
>       u_long          bd_rdStart;     /* when the read started */
>       int             bd_rnonblock;   /* true if nonblocking reads are set */
>       struct bpf_program_smr
> 

-- 
:wq Claudio

Reply via email to