> You have a directory and change something in it - there are dirty hashed
> buffers covering directory.
>
> You erase that directory - as there is no bforget, there are still dirty
> hashed buffers.
>
> You alloc file at that place. Buffers containing former directory are
> flushed over the file.
>
> I think bforget must be called always when you release some structure that
> was accessed using bread/brelse.
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.
Let's see:
something does rmdir() on a directory. It dirtifies the blocks. Soon after
that iput() calls ext2_delete_inode(). It calls ext2_truncate(). For
simplicity we can assume the directory was short. trunc_direct() happily
calls ext2_free_blocks() and calls it quits, leaving the dirty buffers in
the buffer cache. Later the corresponding on-disk blocks are allocated by
regular file. After that kflushd does its thing and corrupts the data.
Damn.
Stephen, Ingo, could you look at the stuff above? Methink it means that we
either must separate ext2_truncate() for directories (doing bforget() on
the data blocks) _or_ put the directory blocks into the page cache and do
block_flush(). I'ld rather prefer the latter. Moreover, we can stuff the
indirect blocks into the page cache too (using negative offsets). That
would leave us with pure buffer cache only for static structures.
Comments?
Al
-
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/