summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/devfs/devfs_vfsops.c
diff options
context:
space:
mode:
authordf125853 <none@none>2007-08-19 08:22:40 -0700
committerdf125853 <none@none>2007-08-19 08:22:40 -0700
commitf94a2171d4b7fbadf2185e11edc1992ab6778857 (patch)
tree71d60ed66e8d143a210e450f980cebd50fc78943 /usr/src/uts/common/fs/devfs/devfs_vfsops.c
parent8bfe3c7bb1fe581a62574aa58af260ffdba7993b (diff)
downloadillumos-joyent-f94a2171d4b7fbadf2185e11edc1992ab6778857.tar.gz
6526639 Deadlock in fcp code : fp_nexus_enum_tq taskq deadlocks with devfs
Diffstat (limited to 'usr/src/uts/common/fs/devfs/devfs_vfsops.c')
-rw-r--r--usr/src/uts/common/fs/devfs/devfs_vfsops.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/usr/src/uts/common/fs/devfs/devfs_vfsops.c b/usr/src/uts/common/fs/devfs/devfs_vfsops.c
index 25f8f061f3..ddd006ab70 100644
--- a/usr/src/uts/common/fs/devfs/devfs_vfsops.c
+++ b/usr/src/uts/common/fs/devfs/devfs_vfsops.c
@@ -358,11 +358,11 @@ devfs_clean_vhci(dev_info_t *dip, void *args)
(void) tsd_set(devfs_clean_key, (void *)1);
dvp = devfs_dip_to_dvnode(dip);
- (void) tsd_set(devfs_clean_key, NULL);
if (dvp) {
(void) dv_cleandir(dvp, NULL, flags);
VN_RELE(DVTOV(dvp));
}
+ (void) tsd_set(devfs_clean_key, NULL);
return (DDI_WALK_CONTINUE);
}
@@ -380,6 +380,11 @@ devfs_clean_vhci(dev_info_t *dip, void *args)
* referenced dv_nodes. To enforce this, devfs_clean() always
* returns success i.e. 0.
*
+ * devfs_clean() may return before removing all possible nodes if
+ * we cannot acquire locks in areas of the code where potential for
+ * deadlock exists (see comments in dv_find() and dv_cleandir() for
+ * examples of this).
+ *
* devfs caches unreferenced dv_node to speed by the performance
* of ls, find, etc. devfs_clean() is invoked to cleanup cached
* dv_nodes to reclaim memory as well as to facilitate device
@@ -404,11 +409,13 @@ devfs_clean(dev_info_t *dip, char *devnm, uint_t flags)
/* avoid recursion back into the device tree */
(void) tsd_set(devfs_clean_key, (void *)1);
dvp = devfs_dip_to_dvnode(dip);
- (void) tsd_set(devfs_clean_key, NULL);
- if (dvp == NULL)
+ if (dvp == NULL) {
+ (void) tsd_set(devfs_clean_key, NULL);
return (0);
+ }
(void) dv_cleandir(dvp, devnm, flags);
+ (void) tsd_set(devfs_clean_key, NULL);
VN_RELE(DVTOV(dvp));
/*