lkml.org 
[lkml]   [1999]   [Jun]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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/

\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.825 / U:0.116 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site