ext2 2.3.x race fixes

From: Andrea Arcangeli (andrea@suse.de)
Date: Sat Jan 08 2000 - 11:02:47 EST


This patch fixes a cupole of races in ext2 in 2.3.36:

diff -urN 2.3.36pre5/fs/ext2/fsync.c 2.3.36pre5-ext2/fs/ext2/fsync.c
--- 2.3.36pre5/fs/ext2/fsync.c Wed Dec 8 00:05:27 1999
+++ 2.3.36pre5-ext2/fs/ext2/fsync.c Tue Jan 4 17:39:51 2000
@@ -23,6 +23,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/locks.h>
 
 
 
@@ -40,10 +41,21 @@
         if (!bh)
                 return 0;
         if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
+ /* There can be a parallell read(2) that started read-I/O
+ on the buffer so we can't assume that there's been
+ an I/O error without first waiting I/O completation. */
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh))
+ {
+ brelse (bh);
+ return -1;
+ }
         }
         if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+ if (wait)
+ /* when we return from fsync all the blocks
+ must be _just_ stored on disk */
+ wait_on_buffer(bh);
                 brelse(bh);
                 return 0;
         }
diff -urN 2.3.36pre5/fs/ext2/inode.c 2.3.36pre5-ext2/fs/ext2/inode.c
--- 2.3.36pre5/fs/ext2/inode.c Tue Dec 14 15:48:51 1999
+++ 2.3.36pre5-ext2/fs/ext2/inode.c Tue Jan 4 17:31:28 2000
@@ -254,6 +254,8 @@
         }
         if (metadata) {
                 result = getblk (inode->i_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
                 memset(result->b_data, 0, blocksize);
                 mark_buffer_uptodate(result, 1);
                 mark_buffer_dirty(result, 1);
@@ -363,6 +365,8 @@
                 goto out;
         if (metadata) {
                 result = getblk (bh->b_dev, tmp, blocksize);
+ if (!buffer_uptodate(result))
+ wait_on_buffer(result);
                 memset(result->b_data, 0, inode->i_sb->s_blocksize);
                 mark_buffer_uptodate(result, 1);
                 mark_buffer_dirty(result, 1);
@@ -542,6 +546,8 @@
                 struct buffer_head *bh;
                 bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
                 if (buffer_new(&dummy)) {
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
                         memset(bh->b_data, 0, inode->i_sb->s_blocksize);
                         mark_buffer_uptodate(bh, 1);
                         mark_buffer_dirty(bh, 1);

Andrea

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Jan 15 2000 - 21:00:12 EST