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.
This commit is contained in:
Tor Egge 2005-10-09 20:15:15 +00:00
parent d4d530da96
commit 021869b542

View File

@ -681,6 +681,17 @@ ffs_snapshot(mp, snapfile)
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);