Messages in this thread Patch in this message | | | Date | Sun, 27 Jun 1999 16:16:08 +0200 (CEST) | From | Andrea Arcangeli <> | Subject | [patch] possible ext2 problem in inode_getblk() (2.3.[789]) |
| |
I think I seen a potential race, here it is a patch against pre4. The problem is that mark_buffer_dirty() may sleep in inode_getblk().
I am getting ext2 troubles with my tree running a memory hog + bonnie at the same time. A clean pre-2.3.9-4 instead is rock solid. Precisely the message I get is this:
ext2_free_blocks: bit already cleared for block 769231
It happens after half an hour of stress testing. After such message everything continue fine (no sign of corruption too). Even the patch below make no differences. The additional ext2_free_blocks happens in trunc_indirect. Now I'll try to find who is previously releasing the blocks.
Index: linux/fs/ext2/inode.c =================================================================== RCS file: /var/cvs/linux/fs/ext2/inode.c,v retrieving revision 1.1.2.10 diff -u -r1.1.2.10 inode.c --- linux/fs/ext2/inode.c 1999/06/26 13:19:31 1.1.2.10 +++ linux/fs/ext2/inode.c 1999/06/27 02:34:47 @@ -265,7 +265,7 @@ tmp = le32_to_cpu(*p); if (tmp) { if (metadata) { - struct buffer_head * result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); + result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); if (tmp == le32_to_cpu(*p)) return result; brelse (result); @@ -318,14 +318,14 @@ return NULL; if (metadata) { result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); + memset(result->b_data, 0, inode->i_sb->s_blocksize); + mark_buffer_uptodate(result, 1); + mark_buffer_dirty(result, 1); if (*p) { ext2_free_blocks (inode, tmp, 1); - brelse (result); + bforget (result); goto repeat; } - memset(result->b_data, 0, inode->i_sb->s_blocksize); - mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); } else { if (*p) { ext2_free_blocks (inode, tmp, 1); @@ -430,24 +430,23 @@ } if (metadata) { result = getblk (bh->b_dev, tmp, blocksize); + memset(result->b_data, 0, inode->i_sb->s_blocksize); + mark_buffer_uptodate(result, 1); + mark_buffer_dirty(result, 1); if (*p) { ext2_free_blocks (inode, tmp, 1); - brelse (result); + bforget (result); goto repeat; } - memset(result->b_data, 0, inode->i_sb->s_blocksize); - mark_buffer_uptodate(result, 1); - mark_buffer_dirty(result, 1); } else { + if (*p) { + ext2_free_blocks (inode, tmp, 1); + goto repeat; + } *phys_block = tmp; result = NULL; *err = 0; *created = 1; - } - if (*p) { - ext2_free_blocks (inode, tmp, 1); - brelse (result); - goto repeat; } *p = le32_to_cpu(tmp); mark_buffer_dirty(bh, 1);
Andrea Arcangeli
- 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/
| |