freebsd-dev/sys/ufs/ffs
Kirk McKusick 988fd417a0 Bug 211013 reports that a write error to a UFS filesystem running
with softupdates panics the kernel. The problem that has been pointed
out is that when there is a transient write error on certain metadata
blocks, specifically directory blocks (PAGEDEP), inode blocks
(INODEDEP), indirect pointer blocks (INDIRDEPS), and cylinder group
(BMSAFEMAP, but only when journaling is enabled), we get a panic
in one of the routines called by softdep_disk_io_initiation that
the I/O is "already started" when we retry the write.

These dependency types potentially need to do roll-backs when called
by softdep_disk_io_initiation before doing a write and then a
roll-forward when called by softdep_disk_write_complete after the
I/O completes.  The panic happens when there is a transient error.
At the top of softdep_disk_write_complete we check to see if the
write had an error and if an error occurred we just return.  This
return is correct most of the time because the main role of the routines
called by softdep_disk_write_complete is to process the now-completed
dependencies so that the next I/O steps can happen.

But for the four types listed above, they do not get to do their
rollback operations. This causes the panic when softdep_disk_io_initiation
gets called on the second attempt to do the write and the roll-back
routines find that the roll-backs have already been done. As an
aside I note that there is also the problem that the buffer will
have been unlocked and thus made visible to the filesystem and to
user applications with the roll-backs in place.

The way to resolve the problem is to add a flag to the routines called
by softdep_disk_write_complete for the four dependency types noted
that indicates whether the write was successful (WRITESUCCEEDED).
If the write does not succeed, they do just the roll-backs and then
return. If the write was successful they also do their usual
processing of the now-completed dependencies.

The fix was tested by selectively injecting write errors for buffers
holding dependencies of each of the four types noted above and then
verifying that the kernel no longer paniced and that following the
successful retry of the write that the filesystem could be unmounted
and successfully checked cleanly.

PR: 211013
Reviewed by: kib
2016-08-16 21:02:30 +00:00
..
ffs_alloc.c arc4random() returns 0 to (2**32)−1, use an alternative to initialize 2016-05-22 14:31:20 +00:00
ffs_balloc.c In UFS_BALLOC(), invalidate pages of indirect buffers on failed block 2016-08-16 17:30:58 +00:00
ffs_extern.h Implement VOP_FDATASYNC() for UFS. 2016-08-15 19:22:23 +00:00
ffs_inode.c If IO_SYNC was passed to ffs_truncate(), request synchronous inode 2016-05-17 21:30:58 +00:00
ffs_rawread.c Refactor unmapped buffer address handling. 2015-07-23 19:13:41 +00:00
ffs_snapshot.c Replace all remaining calls to vprint(9) with vn_printf(9), and remove 2016-08-10 16:12:31 +00:00
ffs_softdep.c Bug 211013 reports that a write error to a UFS filesystem running 2016-08-16 21:02:30 +00:00
ffs_subr.c - Make 'struct buf *buf' private to vfs_bio.c. Having a global variable 2015-07-29 02:26:57 +00:00
ffs_suspend.c Remove several write-only variables, all reported by the gcc 4.9 2015-05-29 13:24:17 +00:00
ffs_tables.c
ffs_vfsops.c arc4random() returns 0 to (2**32)−1, use an alternative to initialize 2016-05-22 14:31:20 +00:00
ffs_vnops.c Implement VOP_FDATASYNC() for UFS. 2016-08-15 19:22:23 +00:00
fs.h UFS: spelling fixes on comments. 2016-04-29 20:43:51 +00:00
softdep.h Bug 211013 reports that a write error to a UFS filesystem running 2016-08-16 21:02:30 +00:00