hey, thanks for all the fixes!

I'm trying to import a driver (while being very new to
networking/driver stuff), and updating to -current fixed an issue I've
had, most likely from this commit.

Now my ported driver is close to working :-)

On Sat, Apr 28, 2018 at 08:16:15AM +0000, Maxime Villard wrote:
> Module Name:  src
> Committed By: maxv
> Date:         Sat Apr 28 08:16:15 UTC 2018
> 
> Modified Files:
>       src/sys/kern: uipc_mbuf.c
> 
> Log Message:
> Modify m_defrag, so that it never frees the first mbuf of the chain. While
> here use the given 'flags' argument, and not M_DONTWAIT.
> 
> We have a problem with several drivers: they poll an mbuf chain from their
> queues and call m_defrag on them, but m_defrag could update the mbuf
> pointer, so the mbuf in the queue is no longer valid. It is not easy to
> fix each driver, because doing pop+push will reorder the queue, and we
> don't really want that to happen.
> 
> This problem was independently spotted by me, Kengo, Masanobu, and other
> people too it seems (perhaps PR/53218).
> 
> Now m_defrag leaves the first mbuf in place, and compresses the chain
> only starting from the second mbuf in the chain.
> 
> It is important not to compress the first mbuf with hacks, because the
> storage of this first mbuf may be shared with other mbufs.
> 
> 
> To generate a diff of this commit:
> cvs rdiff -u -r1.210 -r1.211 src/sys/kern/uipc_mbuf.c
> 
> Please note that diffs are not public domain; they are subject to the
> copyright notices on the relevant files.
> 

> Modified files:
> 
> Index: src/sys/kern/uipc_mbuf.c
> diff -u src/sys/kern/uipc_mbuf.c:1.210 src/sys/kern/uipc_mbuf.c:1.211
> --- src/sys/kern/uipc_mbuf.c:1.210    Fri Apr 27 19:06:48 2018
> +++ src/sys/kern/uipc_mbuf.c  Sat Apr 28 08:16:15 2018
> @@ -1,4 +1,4 @@
> -/*   $NetBSD: uipc_mbuf.c,v 1.210 2018/04/27 19:06:48 maxv Exp $     */
> +/*   $NetBSD: uipc_mbuf.c,v 1.211 2018/04/28 08:16:15 maxv Exp $     */
>  
>  /*
>   * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
> @@ -62,7 +62,7 @@
>   */
>  
>  #include <sys/cdefs.h>
> -__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.210 2018/04/27 19:06:48 maxv Exp 
> $");
> +__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.211 2018/04/28 08:16:15 maxv Exp 
> $");
>  
>  #ifdef _KERNEL_OPT
>  #include "opt_mbuftrace.h"
> @@ -1475,27 +1475,32 @@ enobufs:
>  }
>  
>  /*
> - * Copy the mbuf chain to a new mbuf chain that is as short as possible.
> - * Return the new mbuf chain on success, NULL on failure.  On success,
> - * free the old mbuf chain.
> + * Compress the mbuf chain. Return the new mbuf chain on success, NULL on
> + * failure. The first mbuf is preserved, and on success the pointer returned
> + * is the same as the one passed.
>   */
>  struct mbuf *
>  m_defrag(struct mbuf *mold, int flags)
>  {
>       struct mbuf *m0, *mn, *n;
> -     size_t sz = mold->m_pkthdr.len;
> +     int sz;
>  
>       KASSERT((mold->m_flags & M_PKTHDR) != 0);
>  
> -     m0 = m_gethdr(flags, MT_DATA);
> +     if (mold->m_next == NULL)
> +             return mold;
> +
> +     m0 = m_get(flags, MT_DATA);
>       if (m0 == NULL)
>               return NULL;
> -     M_COPY_PKTHDR(m0, mold);
>       mn = m0;
>  
> +     sz = mold->m_pkthdr.len - mold->m_len;
> +     KASSERT(sz >= 0);
> +
>       do {
> -             if (sz > MHLEN) {
> -                     MCLGET(mn, M_DONTWAIT);
> +             if (sz > MLEN) {
> +                     MCLGET(mn, flags);
>                       if ((mn->m_flags & M_EXT) == 0) {
>                               m_freem(m0);
>                               return NULL;
> @@ -1511,7 +1516,7 @@ m_defrag(struct mbuf *mold, int flags)
>  
>               if (sz > 0) {
>                       /* need more mbufs */
> -                     n = m_get(M_NOWAIT, MT_DATA);
> +                     n = m_get(flags, MT_DATA);
>                       if (n == NULL) {
>                               m_freem(m0);
>                               return NULL;
> @@ -1522,9 +1527,10 @@ m_defrag(struct mbuf *mold, int flags)
>               }
>       } while (sz > 0);
>  
> -     m_freem(mold);
> +     m_freem(mold->m_next);
> +     mold->m_next = m0;
>  
> -     return m0;
> +     return mold;
>  }
>  
>  void
> 

Reply via email to