Re: 1352 NUL bytes at the end of a page? (was Re: Assertion `s && s->tree' failed: The saga continues.)

Chris Mason
2004-05-17T20:22:33Z

On Mon, 2004-05-17 at 11:23, Chris Mason wrote:

> You've described it correctly for reiserfs though, we unlock the page
> too soon. I'll fix the page locking for reiserfs_file_write. Steven,
> we need to figure out why you're seeing this on ext3.

Steven, could you give this a try as well? It is against 2.6.6-mm3, but
should work against vanilla too:

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

Index: linux.mm/fs/reiserfs/file.c
===================================================================
--- linux.mm.orig/fs/reiserfs/file.c 2004-05-17 13:42:02.000000000 -0400
+++ linux.mm/fs/reiserfs/file.c 2004-05-17 16:22:35.135105528 -0400
@@ -10,6 +10,7 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/pagemap.h>
+#include <linux/swap.h>
#include <linux/writeback.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
@@ -678,10 +679,6 @@
// we only remember error status to report it on
// exit.
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,
* we can safely update i_size and close any running transaction
@@ -718,6 +715,17 @@
reiserfs_write_unlock(inode->i_sb);
}
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;
}