freebsd-nq/sys/ufs/ffs
Kirk McKusick 35338e6091 This change avoids a kernel deadlock on "snaplk" when using
snapshots on UFS filesystems running with journaled soft updates.
This is the first of several bugs that need to be fixed before
removing the restriction added in -r230250 to prevent the use
of snapshots on filesystems running with journaled soft updates.

The deadlock occurs when holding the snapshot lock (snaplk)
and then trying to flush an inode via ffs_update(). We become
blocked by another process trying to flush a different inode
contained in the same inode block that we need. It holds the
inode block for which we are waiting locked. When it tries to
write the inode block, it gets blocked waiting for the our
snaplk when it calls ffs_copyonwrite() to see if the inode
block needs to be copied in our snapshot.

The most obvious place that this deadlock arises is in the
ffs_copyonwrite() routine when it updates critical metadata
in a snapshot and tries to write it out before proceeding.
The fix here is to write the data and indirect block pointer
for the snapshot, but to skip the call to ffs_update() to
write the snapshot inode. To ensure that we will never have
to update a pointer in the inode itself, the ffs_snapshot()
routine that creates the snapshot has to ensure that all the
direct blocks are allocated as part of the creation of the
snapshot.

A less obvious place that this deadlock occurs is when we hold
the snaplk because we are deleting a snapshot. In the course of
doing the deletion, we need to allocate various soft update
dependency structures and allocate some journal space. If we
hit a resource limit while doing this we decrease the resources
in use by flushing out an existing dirty file to get it to give
up the soft dependency resources that it holds. The flush can
cause an ffs_update() to be done on the inode for the file that
we have selected to flush resulting in the same deadlock as
described above when the inode that we have chosen to flush
resides in the same inode block as the snapshot inode that we hold.
The fix is to defer cleaning up any time that the inode on which
we are operating is a snapshot.

Help and review by:    Jeff Roberson
Tested by:             Peter Holm
MFC (to 9 only) after: 2 weeks
2012-03-01 18:45:25 +00:00
..
ffs_alloc.c Migrate ufs and ext2fs from skpc() to memcchr(). 2012-01-01 20:47:33 +00:00
ffs_balloc.c Use 'curthread_pflags' instead of 'thread_pflags' to signify that only 2011-07-09 15:16:07 +00:00
ffs_extern.h This change avoids a kernel deadlock on "snaplk" when using 2012-03-01 18:45:25 +00:00
ffs_inode.c This change avoids a kernel deadlock on "snaplk" when using 2012-03-01 18:45:25 +00:00
ffs_rawread.c Put the general logic for being a CPU hog into a new function 2011-02-02 16:35:10 +00:00
ffs_snapshot.c This change avoids a kernel deadlock on "snaplk" when using 2012-03-01 18:45:25 +00:00
ffs_softdep.c This change avoids a kernel deadlock on "snaplk" when using 2012-03-01 18:45:25 +00:00
ffs_subr.c - Merge soft-updates journaling from projects/suj/head into head. This 2010-04-24 07:05:35 +00:00
ffs_tables.c
ffs_vfsops.c In the original days of BSD, a sync was issued on every filesystem 2012-02-07 20:43:28 +00:00
ffs_vnops.c This change avoids a kernel deadlock on "snaplk" when using 2012-03-01 18:45:25 +00:00
fs.h Use implementation independent inoNN_t scalars for on-disk UFS structures 2011-11-09 07:48:48 +00:00
softdep.h - Speed up pendingblock processing again. Having too much delay between 2011-07-04 22:08:04 +00:00