Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Nov 2017 10:31:49 -0800
From:      Conrad Meyer <cem@freebsd.org>
To:        Emmanuel Vadot <manu@freebsd.org>
Cc:        src-committers <src-committers@freebsd.org>, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r326394 - head/sys/fs/devfs
Message-ID:  <CAG6CVpUe5jD6mWp7LQUGiy4Ova6XeVW%2B34JhvFw-N=X8=j0vDw@mail.gmail.com>
In-Reply-To: <201711301238.vAUCcgrC091396@repo.freebsd.org>
References:  <201711301238.vAUCcgrC091396@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This moves the M_WAITOK (sleepable) memory allocation under
dirlist_mtx, which is an ordinary mutex.  If you run this under
WITNESS, it will (rightfully) complain.  Please revert this change.

One possible way to accomplish the goal you have in mind is a fallback
path if the devfs_dir_findent_locked misses.  E.g.:

=====================================8<==================================
--- a/sys/fs/devfs/devfs_dir.c
+++ b/sys/fs/devfs/devfs_dir.c
@@ -96,19 +96,27 @@ devfs_dir_ref(const char *dir)
        if (*dir == '\0')
                return;

-       dle_new = malloc(sizeof(*dle), M_DEVFS4, M_WAITOK);
-       dle_new->dir = strdup(dir, M_DEVFS4);
-       dle_new->refcnt = 1;
+       dle_new = NULL;

+again:
        mtx_lock(&dirlist_mtx);
        dle = devfs_dir_findent_locked(dir);
        if (dle != NULL) {
                dle->refcnt++;
                mtx_unlock(&dirlist_mtx);
-               free(dle_new->dir, M_DEVFS4);
-               free(dle_new, M_DEVFS4);
+               if (dle_new != NULL) {
+                       free(dle_new->dir, M_DEVFS4);
+                       free(dle_new, M_DEVFS4);
+               }
                return;
        }
+       if (dle_new == NULL) {
+               mtx_unlock(&dirlist_mtx);
+               dle_new = malloc(sizeof(*dle), M_DEVFS4, M_WAITOK);
+               dle_new->dir = strdup(dir, M_DEVFS4);
+               dle_new->refcnt = 1;
+               goto again;
+       }
        LIST_INSERT_HEAD(&devfs_dirlist, dle_new, link);
        mtx_unlock(&dirlist_mtx);
 }
=====================================8<==================================

The downside of this method is we potentially have to take the dirlist
mutex twice.  An even more "optimized" approach would be to M_NOWAIT
the allocations inside the lock and fallback if those fail.  But that
introduces even more code complexity.

Best,
Conrad

On Thu, Nov 30, 2017 at 4:38 AM, Emmanuel Vadot <manu@freebsd.org> wrote:
> Author: manu
> Date: Thu Nov 30 12:38:42 2017
> New Revision: 326394
> URL: https://svnweb.freebsd.org/changeset/base/326394
>
> Log:
>   devfs: Avoid a malloc/free if we just need to increment the refcount
>
>   MFC after:    1 week
>   Sponsored by: Gandi.net
>
> Modified:
>   head/sys/fs/devfs/devfs_dir.c
>
> Modified: head/sys/fs/devfs/devfs_dir.c
> ==============================================================================
> --- head/sys/fs/devfs/devfs_dir.c       Thu Nov 30 12:22:15 2017        (r326393)
> +++ head/sys/fs/devfs/devfs_dir.c       Thu Nov 30 12:38:42 2017        (r326394)
> @@ -98,19 +98,18 @@ devfs_dir_ref(const char *dir)
>         if (*dir == '\0')
>                 return;
>
> -       dle_new = malloc(sizeof(*dle), M_DEVFS4, M_WAITOK);
> -       dle_new->dir = strdup(dir, M_DEVFS4);
> -       dle_new->refcnt = 1;
> -
>         mtx_lock(&dirlist_mtx);
>         dle = devfs_dir_findent_locked(dir);
>         if (dle != NULL) {
>                 dle->refcnt++;
>                 mtx_unlock(&dirlist_mtx);
> -               free(dle_new->dir, M_DEVFS4);
> -               free(dle_new, M_DEVFS4);
>                 return;
>         }
> +
> +       dle_new = malloc(sizeof(*dle), M_DEVFS4, M_WAITOK);
> +       dle_new->dir = strdup(dir, M_DEVFS4);
> +       dle_new->refcnt = 1;
> +
>         LIST_INSERT_HEAD(&devfs_dirlist, dle_new, link);
>         mtx_unlock(&dirlist_mtx);
>  }
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpUe5jD6mWp7LQUGiy4Ova6XeVW%2B34JhvFw-N=X8=j0vDw>