summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authormishra <none@none>2007-01-20 20:57:44 -0800
committermishra <none@none>2007-01-20 20:57:44 -0800
commit46ac44687e556b31f3a5cb070be6bfc79ffb5ea2 (patch)
treecf1dca51b05ecb9fdb819b478c9c8cfd1f69d082 /usr/src
parent494a4c5197688884a8a9a926ffc8d6627ba3bc1b (diff)
downloadillumos-gate-46ac44687e556b31f3a5cb070be6bfc79ffb5ea2.tar.gz
4900516 Deadlock between mutex ulp->ul_lock and pagelock p_selock lead to hanging procs
6406526 setting and clearing T_DONTBLOCK in ufs_flush() causes panic
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/ufs/ufs_lockfs.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/usr/src/uts/common/fs/ufs/ufs_lockfs.c b/usr/src/uts/common/fs/ufs/ufs_lockfs.c
index 11cdcabd4c..4cfe0d1867 100644
--- a/usr/src/uts/common/fs/ufs/ufs_lockfs.c
+++ b/usr/src/uts/common/fs/ufs/ufs_lockfs.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -331,6 +331,7 @@ ufs_flush(struct vfs *vfsp)
int saverror = 0;
struct ufsvfs *ufsvfsp = (struct ufsvfs *)vfsp->vfs_data;
struct fs *fs = ufsvfsp->vfs_fs;
+ int tdontblock = 0;
ASSERT(vfs_lock_held(vfsp));
@@ -402,14 +403,26 @@ ufs_flush(struct vfs *vfsp)
if (ul->un_flags & LDL_NOROLL) {
ASSERT(mtm->mtm_nme == 0);
} else {
- curthread->t_flag |= T_DONTBLOCK;
+ /*
+ * Do not set T_DONTBLOCK if there is a
+ * transaction opened by caller.
+ */
+ if (curthread->t_flag & T_DONTBLOCK)
+ tdontblock = 1;
+ else
+ curthread->t_flag |= T_DONTBLOCK;
+
TRANS_BEGIN_SYNC(ufsvfsp, TOP_COMMIT_FLUSH,
TOP_COMMIT_SIZE, error);
+
if (!error) {
TRANS_END_SYNC(ufsvfsp, saverror,
TOP_COMMIT_FLUSH, TOP_COMMIT_SIZE);
}
- curthread->t_flag &= ~T_DONTBLOCK;
+
+ if (tdontblock == 0)
+ curthread->t_flag &= ~T_DONTBLOCK;
+
logmap_roll_dev(ufsvfsp->vfs_log);
}
}
@@ -864,6 +877,7 @@ ufs__fiolfs(
extern struct pollhead ufs_pollhd;
ulockfs_info_t *head;
ulockfs_info_t *info;
+ int signal = 0;
/* check valid lock type */
if (!lockfsp || lockfsp->lf_lock > LOCKFS_MAXLOCK)
@@ -986,8 +1000,20 @@ ufs__fiolfs(
/*
* Quiesce (wait for outstanding accesses to finish)
*/
- if (error = ufs_quiesce(ulp))
+ if (error = ufs_quiesce(ulp)) {
+ /*
+ * Interrupted due to signal. There could still be
+ * pending vnops.
+ */
+ signal = 1;
+
+ /*
+ * We do broadcast because lock-status
+ * could be reverted to old status.
+ */
+ cv_broadcast(&ulp->ul_cv);
goto errout;
+ }
/*
* If the fallocate thread requested a write fs lock operation
@@ -1147,7 +1173,15 @@ errout:
bcopy(&lfs, &ulp->ul_lockfs, sizeof (struct lockfs));
ulp->ul_fs_lock = (1 << lfs.lf_lock);
}
- (void) ufs_thaw(vfsp, ufsvfsp, ulp);
+
+ /*
+ * Don't call ufs_thaw() when there's a signal during
+ * ufs quiesce operation as it can lead to deadlock
+ * with getpage.
+ */
+ if (signal == 0)
+ (void) ufs_thaw(vfsp, ufsvfsp, ulp);
+
ULOCKFS_CLR_BUSY(ulp);
LOCKFS_CLR_BUSY(&ulp->ul_lockfs);