git: 4ddb3cc5973b - main - devfs(4): defer freeing until we drop devmtx ("cdev")

Edward Tomasz Napierala trasz at FreeBSD.org
Tue Dec 29 14:06:26 UTC 2020


The branch main has been updated by trasz:

URL: https://cgit.FreeBSD.org/src/commit/?id=4ddb3cc5973b94b0502e1683accac87998235857

commit 4ddb3cc5973b94b0502e1683accac87998235857
Author:     Edward Tomasz Napierala <trasz at FreeBSD.org>
AuthorDate: 2020-12-29 13:45:53 +0000
Commit:     Edward Tomasz Napierala <trasz at FreeBSD.org>
CommitDate: 2020-12-29 13:47:36 +0000

    devfs(4): defer freeing until we drop devmtx ("cdev")
    
    Before r332974 the old code would sometimes cause a rare lock order
    reversal against pagequeue, which looked roughly like this:
    
    witness_checkorder()
    __mtx_lock-flags()
    vm_page_alloc()
    uma_small_alloc()
    keg_alloc_slab()
    keg_fetch-slab()
    zone_fetch-slab()
    zone_import()
    zone_alloc_bucket()
    uma_zalloc_arg()
    bucket_alloc()
    uma_zfree_arg()
    free()
    devfs_metoo()
    devfs_populate_loop()
    devfs_populate()
    devfs_rioctl()
    VOP_IOCTL_APV()
    VOP_IOCTL()
    vn_ioctl()
    fo_ioctl()
    kern_ioctl()
    sys_ioctl()
    
    Since r332974 the original problem no longer exists, but it still
    makes sense to move things out of the - often congested - lock.
    
    Reviewed By:    kib, markj
    Sponsored by:   NetApp, Inc.
    Sponsored by:   Klara, Inc.
    Differential Revision: https://reviews.freebsd.org/D27334
---
 sys/fs/devfs/devfs_devs.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index cb2db0c1b8b5..19619d94ba1c 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -482,7 +482,7 @@ devfs_purge(struct devfs_mount *dm, struct devfs_dirent *dd)
 static void
 devfs_metoo(struct cdev_priv *cdp, struct devfs_mount *dm)
 {
-	struct devfs_dirent **dep;
+	struct devfs_dirent **dep, **olddep;
 	int siz;
 
 	siz = (dm->dm_idx + 1) * sizeof *dep;
@@ -495,8 +495,7 @@ devfs_metoo(struct cdev_priv *cdp, struct devfs_mount *dm)
 		return;
 	} 
 	memcpy(dep, cdp->cdp_dirents, (cdp->cdp_maxdirent + 1) * sizeof *dep);
-	if (cdp->cdp_maxdirent > 0)
-		free(cdp->cdp_dirents, M_DEVFS2);
+	olddep = cdp->cdp_maxdirent > 0 ? cdp->cdp_dirents : NULL;
 	cdp->cdp_dirents = dep;
 	/*
 	 * XXX: if malloc told us how much we actually got this could
@@ -504,6 +503,7 @@ devfs_metoo(struct cdev_priv *cdp, struct devfs_mount *dm)
 	 */
 	cdp->cdp_maxdirent = dm->dm_idx;
 	dev_unlock();
+	free(olddep, M_DEVFS2);
 }
 
 /*


More information about the dev-commits-src-all mailing list