]> Git Repo - linux.git/commit - mm/filemap.c
Fix read/truncate race
authorNeilBrown <[email protected]>
Tue, 17 Jul 2007 11:03:04 +0000 (04:03 -0700)
committerLinus Torvalds <[email protected]>
Tue, 17 Jul 2007 17:22:59 +0000 (10:22 -0700)
commita32ea1e1f925399e0d81ca3f7394a44a6dafa12c
treefade44f4d7baf5695a856ad73e6b98f0d6edf9de
parente21ea246bce5bb93dd822de420172ec280aed492
Fix read/truncate race

do_generic_mapping_read currently samples the i_size at the start and doesn't
do so again unless it needs to call ->readpage to load a page.  After
->readpage it has to re-sample i_size as a truncate may have caused that page
to be filled with zeros, and the read() call should not see these.

However there are other activities that might cause ->readpage to be called on
a page between the time that do_generic_mapping_read samples i_size and when
it finds that it has an uptodate page.  These include at least read-ahead and
possibly another thread performing a read.

So do_generic_mapping_read must sample i_size *after* it has an uptodate page.
 Thus the current sampling at the start and after a read can be replaced with
a sampling before the copy-out.

The same change applied to __generic_file_splice_read.

Note that this fixes any race with truncate_complete_page, but does not fix a
possible race with truncate_partial_page.  If a partial truncate happens after
do_generic_mapping_read samples i_size and before the copy_out, the nuls that
truncate_partial_page place in the page could be copied out incorrectly.

I think the best fix for that is to *not* zero out parts of the page in
truncate_partial_page, but rather to zero out the tail of a page when
increasing i_size.

Signed-off-by: Neil Brown <[email protected]>
Cc: Jens Axboe <[email protected]>
Acked-by: Nick Piggin <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
mm/filemap.c
This page took 0.066546 seconds and 4 git commands to generate.