aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Jeffery <djeffery@redhat.com>2015-08-28 14:50:45 +1000
committerBen Hutchings <ben@decadent.org.uk>2015-10-13 03:46:07 +0100
commitff8c37e67a9b4a8e8442c601fc2a557f58d99c2c (patch)
tree04e9af2485355f630f8358615df59b2b219d87fe
parentb0e0b3d02b17bdcdfeef2fc96d6a3e76c76bb153 (diff)
downloadkernel_samsung_smdk4412-ff8c37e67a9b4a8e8442c601fc2a557f58d99c2c.zip
kernel_samsung_smdk4412-ff8c37e67a9b4a8e8442c601fc2a557f58d99c2c.tar.gz
kernel_samsung_smdk4412-ff8c37e67a9b4a8e8442c601fc2a557f58d99c2c.tar.bz2
xfs: return errors from partial I/O failures to files
commit c9eb256eda4420c06bb10f5e8fbdbe1a34bc98e0 upstream. There is an issue with xfs's error reporting in some cases of I/O partially failing and partially succeeding. Calls like fsync() can report success even though not all I/O was successful in partial-failure cases such as one disk of a RAID0 array being offline. The issue can occur when there are more than one bio per xfs_ioend struct. Each call to xfs_end_bio() for a bio completing will write a value to ioend->io_error. If a successful bio completes after any failed bio, no error is reported do to it writing 0 over the error code set by any failed bio. The I/O error information is now lost and when the ioend is completed only success is reported back up the filesystem stack. xfs_end_bio() should only set ioend->io_error in the case of BIO_UPTODATE being clear. ioend->io_error is initialized to 0 at allocation so only needs to be updated by a failed bio. Also check that ioend->io_error is 0 so that the first error reported will be the error code returned. Signed-off-by: David Jeffery <djeffery@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--fs/xfs/xfs_aops.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index b367581..c2b06d4 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -365,7 +365,8 @@ xfs_end_bio(
xfs_ioend_t *ioend = bio->bi_private;
ASSERT(atomic_read(&bio->bi_cnt) >= 1);
- ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
+ if (!ioend->io_error && !test_bit(BIO_UPTODATE, &bio->bi_flags))
+ ioend->io_error = error;
/* Toss bio and pass work off to an xfsdatad thread */
bio->bi_private = NULL;