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-main
mailing list