Commit 77124e4c authored by Chris Mason's avatar Chris Mason Committed by Linus Torvalds

[PATCH] Fix reiserfs inode size update race

reiserfs_file_write unlocks the pages it operated on before updating
i_size.  This can lead to races with writepage, who checks i_size when
deciding how much of the file to zero out.

This patch also replaces SetPageReferenced with mark_page_accessed() in
reiserfs_file_write

This was verified to fix the BitKeeper data corruption problems that
Steven Cole has been debugging, where concurrent writes to a file and
writebacks to disk would cause zeroes in the file when CONFIG_PREEMPT
was enabled.
parent 4b3b8ee5
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
...@@ -655,10 +656,6 @@ int reiserfs_submit_file_region_for_write( ...@@ -655,10 +656,6 @@ int reiserfs_submit_file_region_for_write(
// we only remember error status to report it on // we only remember error status to report it on
// exit. // exit.
write_bytes-=count; write_bytes-=count;
SetPageReferenced(page);
unlock_page(page); // We unlock the page as it was locked by earlier call
// to grab_cache_page
page_cache_release(page);
} }
/* now that we've gotten all the ordered buffers marked dirty, /* now that we've gotten all the ordered buffers marked dirty,
* we can safely update i_size and close any running transaction * we can safely update i_size and close any running transaction
...@@ -695,6 +692,17 @@ int reiserfs_submit_file_region_for_write( ...@@ -695,6 +692,17 @@ int reiserfs_submit_file_region_for_write(
reiserfs_write_unlock(inode->i_sb); reiserfs_write_unlock(inode->i_sb);
} }
th->t_trans_id = 0; th->t_trans_id = 0;
/*
* we have to unlock the pages after updating i_size, otherwise
* we race with writepage
*/
for ( i = 0; i < num_pages ; i++) {
struct page *page=prepared_pages[i];
unlock_page(page);
mark_page_accessed(page);
page_cache_release(page);
}
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment