summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs/devfs_devs.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2006-09-18 13:23:08 +0000
committerkib <kib@FreeBSD.org>2006-09-18 13:23:08 +0000
commitecf34f450410ca3aac345b52bece9c0fb4ae459c (patch)
treea22547e48d6aa3545a66b54d100fbcab374bd630 /sys/fs/devfs/devfs_devs.c
parente84508ee5e22076fddd4af5d0ca3092768e7e584 (diff)
downloadFreeBSD-src-ecf34f450410ca3aac345b52bece9c0fb4ae459c.zip
FreeBSD-src-ecf34f450410ca3aac345b52bece9c0fb4ae459c.tar.gz
Resolve the devfs deadlock caused by LOR between devfs_mount->dm_lock and
vnode lock in devfs_allocv. Do this by temporary dropping dm_lock around vnode locking. For safe operation, add hold counters for both devfs_mount and devfs_dirent, and DE_DOOMED flag for devfs_dirent. The facilities allow to continue after dropping of the dm_lock, by making sure that referenced memory does not disappear. Reviewed by: tegge Tested by: kris Approved by: kan (mentor) PR: kern/102335
Diffstat (limited to 'sys/fs/devfs/devfs_devs.c')
-rw-r--r--sys/fs/devfs/devfs_devs.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index d933f9f..c8408ce 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -179,6 +179,7 @@ devfs_newdirent(char *name, int namelen)
vfs_timestamp(&de->de_ctime);
de->de_mtime = de->de_atime = de->de_ctime;
de->de_links = 1;
+ de->de_holdcnt = 1;
#ifdef MAC
mac_init_devfsdirent(de);
#endif
@@ -230,9 +231,18 @@ devfs_vmkdir(struct devfs_mount *dmp, char *name, int namelen, struct devfs_dire
}
void
+devfs_dirent_free(struct devfs_dirent *de)
+{
+ free(de, M_DEVFS3);
+}
+
+void
devfs_delete(struct devfs_mount *dm, struct devfs_dirent *de)
{
+ KASSERT((de->de_flags & DE_DOOMED) == 0,
+ ("devfs_delete doomed dirent"));
+ de->de_flags |= DE_DOOMED;
if (de->de_symlink) {
free(de->de_symlink, M_DEVFS);
de->de_symlink = NULL;
@@ -251,7 +261,8 @@ devfs_delete(struct devfs_mount *dm, struct devfs_dirent *de)
free_unr(devfs_inos, de->de_inode);
de->de_inode = 0;
}
- free(de, M_DEVFS3);
+ if (DEVFS_DE_DROP(de))
+ devfs_dirent_free(de);
}
/*
OpenPOWER on IntegriCloud