> Sheesh... Yes, you are right. It was not a problem with the old buffer
> cache, but now... Arrgh. Races in truncate(), film at 11. Pheeewww...
> Unless I'm seriously misunderstanding what happens you've just dug out a
> race in ext2. It doesn't do bforget() on the data blocks in directories.
> If I'm not mistaken the same scenario applies here just fine.

Here goes quick'n'dirty patch. It does bforget(). It should prevent file
corruption.

Mikulas Patocka

--- linux-2.3.19.tar.gz#utar/linux/fs/ext2/truncate.c   Tue Jun 29 18:22:08 1999
+++ linux/fs/ext2/truncate.c    Fri Oct  8 18:40:36 1999
@@ -101,6 +101,14 @@
  *             -- WSH, 1998
  */
 
+/* M.P.: quick & dirty patch to prevent data corruption */
+
+static void brelse_blocks(struct inode *i, unsigned long block_to_free, unsigned long 
+count)
+{
+       while (count--)
+               bforget(get_hash_table(i->i_dev, block_to_free++, 
+i->i_sb->s_blocksize));
+}
+
 /*
  * Check whether any of the slots in an indirect block are
  * still in use, and if not free the block.
@@ -184,14 +192,17 @@
                else if (block_to_free == tmp - free_count)
                        free_count++;
                else {
+                       if (!S_ISREG(inode->i_mode)) brelse_blocks(inode, 
+block_to_free, free_count);
                        ext2_free_blocks (inode, block_to_free, free_count);
                free_this:
                        block_to_free = tmp;
                        free_count = 1;
                }
        }
-       if (free_count > 0)
+       if (free_count > 0) {
+               if (!S_ISREG(inode->i_mode)) brelse_blocks(inode, block_to_free, 
+free_count);
                ext2_free_blocks (inode, block_to_free, free_count);
+       }
        return retry;
 }
 
@@ -247,14 +258,17 @@
                else if (block_to_free == tmp - free_count)
                        free_count++;
                else {
+                       if (!S_ISREG(inode->i_mode)) brelse_blocks(inode, 
+block_to_free, free_count);
                        ext2_free_blocks (inode, block_to_free, free_count);
                free_this:
                        block_to_free = tmp;
                        free_count = 1;
                }
        }
-       if (free_count > 0)
+       if (free_count > 0) {
+               if (!S_ISREG(inode->i_mode)) brelse_blocks(inode, block_to_free, 
+free_count);
                ext2_free_blocks (inode, block_to_free, free_count);
+       }
        /*
         * Check the block and dispose of the ind_bh buffer.
         */

Reply via email to