[PATCH 1/5] direct-io: fix page_errors handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a page error occurs during write request, dio_refill_page() sets
dio->page_errors, maps zero page instead and proceeds as usual if
mapped blocks exist to clear mapped blocks.  After clearing all
blocks, get_more_blocks() is called to map more blocks.  The function
fails if dio->page_errors is set thus propagating the delayed error
condition.

However, the delayed propagation doesn't work if page error occurs for
the last chunk.  get_more_blocks() is not called after clearing
currently mapped buffers; thus, the error condition is not reflected
in the return value.  dio->page_errors is later taken into account in
synchronous completion path but not in async completion path.

This bug can be exposed by direct aio writing a buffer which has the
tailing pages munmapped.  The file blocks corresponding to the
unmapped area are cleared to zero but the write successfully completes
with result set to full length of the request.

This patch fixes the bug by making do_direct_IO() always propagate
page_errors to its return value.  As this makes page_errors
propagation the responsibility of do_direct_IO() proper,
dio->page_errors handling in synchronous completion path is removed.

This patch also fixes error precedence bug in synchronous completion
path.  If both page_errors and io_error occur, page_errors should be
reported to user but the original code gave precedence to IO error
reported from dio_await_completion().

Signed-off-by: Tejun Heo <[email protected]>
---
 fs/direct-io.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/direct-io.c b/fs/direct-io.c
index 5981e17..25721b2 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -940,6 +940,8 @@ next_block:
 		block_in_page = 0;
 	}
 out:
+	if (ret == 0)
+		ret = dio->page_errors;
 	return ret;
 }
 
@@ -1125,8 +1127,6 @@ direct_io_worker(int rw, struct kiocb *i
 		ret2 = dio_await_completion(dio);
 		if (ret == 0)
 			ret = ret2;
-		if (ret == 0)
-			ret = dio->page_errors;
 		if (dio->result) {
 			loff_t i_size = i_size_read(inode);
 
-- 
1.4.3.3


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux