This patch enables a filesystem to do a forcible unmount when the
underlying media fails or generally goes away. For example when a
USB flash memory card hosting a UFS filesystem is unplugged.
The basic strategy for handling disk I/O errors when softdep is enabled
is to stop writing to the disk of the affected file systemand mostly pretend
that all future writes by the file system to that disk actually succeed,
and then trigger an asynchronous forced unmount of the affected file system.
There are two cases for disk I/O errors:
- ENXIO, which means that this disk is gone and the lower layers of the storage stack already guarantee that no future I/O to this disk will succeed.
- EIO (or most other errors), which means that this particular I/O request has failed but subsequence I/O requests to this disk might still succeed.
For ENXIO, we can just clear the error and continue, because we know that
the file system cannot affect the on-disk state after we see this error.
For EIO or other errors, we arrange for the geom_vfs layer to reject
all future I/O requests with ENXIO just like is done when the geom_vfs is
orphaned, and then the file system code can again just clear the error and
continue on.
This new treatment of I/O errors is needed for writes of any buffer that is
involved in a dependency (most of which are explicit via a structure attached
to bp->b_dep, but some of which are implicit), and also for any read that is
necessary to write other buffers which are involved in a dependency.
In this patch we apply the new treatment to all writes and to the specific
reads that are done as part of flushing buffers involved in dependencies.
When such a read actually does fail, we fabricate a buffer full of zeroes
and pretend that the read succeeded. The only case where a buffer full of
zeros causes the code to do the wrong thing is when reading an inode buffer
containing an inode that still has an inodedep in memory that will reinitialize
ip->i_effnlink based on the ip->i_nlink that we read, and to handle this we
now store the ip->i_nlink value that we wrote in the inodedep as well.
fsync() and msync() do need to return errors if data fails to be written
to stable storage, and so these operations return ENXIO for every call made
on files in a file system where we have otherwise been ignoring I/O errors.