summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2005-10-09 20:15:15 +0000
committertegge <tegge@FreeBSD.org>2005-10-09 20:15:15 +0000
commitddad01d50f900652c8bb82a40e51e8b998857e9e (patch)
tree6a4fe84f287c921267419c7f37cbaedc90d909ba /sys
parent1448da0d3a2ecdbfd91f46cc28ce3b67d4096868 (diff)
downloadFreeBSD-src-ddad01d50f900652c8bb82a40e51e8b998857e9e.zip
FreeBSD-src-ddad01d50f900652c8bb82a40e51e8b998857e9e.tar.gz
Reduce probability for a deadlock that can occur when a snapshot inode is
updated by a process holding the snapshot lock. Another process updating a different inode in the same inodeblock will do copy on write checks and lock in the opposite direction. The snapshot code force a copy on write of these blocks manually (cf. start of expunge_ufs[12]) and these inode blocks are later put on snapblklist. This partial fix is to 'drain' the relevant ffs_copyonwrite() operation after installing new snapblklist. This is not a 100% solution since a failed block allocation can cause implicit fsync() which might deadlock before the new snapblklist has been installed.
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 0dc07e9..98a1f23 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -681,6 +681,17 @@ out1:
VI_UNLOCK(devvp);
if (space != NULL)
FREE(space, M_UFSMNT);
+ /*
+ * If another process is currently writing the buffer containing
+ * the inode for this snapshot then a deadlock can occur. Drop
+ * the snapshot lock until the buffer has been written.
+ */
+ VOP_UNLOCK(vp, 0, td);
+ (void) bread(ip->i_devvp,
+ fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
+ (int) fs->fs_bsize, NOCRED, &nbp);
+ brelse(nbp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
done:
FREE(copy_fs->fs_csp, M_UFSMNT);
bawrite(sbp);
OpenPOWER on IntegriCloud