2002-11-06 03:45:33

by Jordan Breeding

[permalink] [raw]
Subject: buffer layer error at fs/buffer.c:1166

Hello,

I get these errors while using 2.5.46-bk:

VFS: brelse: Trying to free free buffer
buffer layer error at fs/buffer.c:1166
Pass this trace through ksymoops for reporting
Call Trace:
[<c01585b6>] __brelse+0x36/0x40
[<c01587d7>] bh_lru_install+0xc7/0x100
[<c0158875>] __find_get_block+0x65/0x70
[<c0158443>] __getblk_slow+0x23/0x110
[<c01588db>] __getblk+0x5b/0x70
[<c01943a8>] ext3_getblk+0xa8/0x300
[<c0194633>] ext3_bread+0x33/0xb0
[<c0197c5f>] dx_probe+0x4f/0x310
[<c0194633>] ext3_bread+0x33/0xb0
[<c01980fd>] ext3_htree_fill_tree+0x9d/0x1d0
[<c0191572>] ext3_dx_readdir+0x92/0x1fa
[<c019114c>] ext3_readdir+0x4bc/0x4f0
[<c01685b0>] filldir64+0x0/0x110
[<c013a8f6>] handle_mm_fault+0x86/0xc0
[<c011c3cc>] do_page_fault+0x22c/0x45c
[<c01682b2>] vfs_readdir+0xb2/0xc0
[<c01685b0>] filldir64+0x0/0x110
[<c016871b>] sys_getdents64+0x5b/0x140
[<c01685b0>] filldir64+0x0/0x110
[<c013b0a3>] sys_brk+0x103/0x130
[<c010af93>] syscall_call+0x7/0xb

VFS: brelse: Trying to free free buffer
buffer layer error at fs/buffer.c:1166
Pass this trace through ksymoops for reporting
Call Trace:
[<c01585b6>] __brelse+0x36/0x40
[<c01587d7>] bh_lru_install+0xc7/0x100
[<c0158875>] __find_get_block+0x65/0x70
[<c0158443>] __getblk_slow+0x23/0x110
[<c01588db>] __getblk+0x5b/0x70
[<c015891f>] __bread+0x2f/0x80
[<c0196523>] ext3_get_inode_loc+0xf3/0x190
[<c016e941>] alloc_inode+0x181/0x1b0
[<c01965de>] ext3_read_inode+0x1e/0x360
[<c016f77e>] iget_locked+0x6e/0x70
[<c0198bf2>] ext3_lookup+0xf2/0x100
[<c0162ab6>] real_lookup+0xd6/0x110
[<c0162d3d>] do_lookup+0x10d/0x170
[<c01631a6>] link_path_walk+0x406/0x7c0
[<c0163ab9>] __user_walk+0x49/0x60
[<c015ebcf>] vfs_stat+0x1f/0x60
[<c015f21b>] sys_stat64+0x1b/0x40
[<c013046c>] sys_rt_sigprocmask+0x12c/0x1f0
[<c010af93>] syscall_call+0x7/0xb

Thanks.

Jordan


2002-11-06 04:27:33

by Andrew Morton

[permalink] [raw]
Subject: Re: buffer layer error at fs/buffer.c:1166

Jordan Breeding wrote:
>
> Hello,
>
> I get these errors while using 2.5.46-bk:
>
> VFS: brelse: Trying to free free buffer
> buffer layer error at fs/buffer.c:1166
> Pass this trace through ksymoops for reporting
> Call Trace:
> [<c01585b6>] __brelse+0x36/0x40
> [<c01587d7>] bh_lru_install+0xc7/0x100
> [<c0158875>] __find_get_block+0x65/0x70
> [<c0158443>] __getblk_slow+0x23/0x110
> [<c01588db>] __getblk+0x5b/0x70
> [<c01943a8>] ext3_getblk+0xa8/0x300
> [<c0194633>] ext3_bread+0x33/0xb0
> [<c0197c5f>] dx_probe+0x4f/0x310
> [<c0194633>] ext3_bread+0x33/0xb0
> [<c01980fd>] ext3_htree_fill_tree+0x9d/0x1d0

There is a refcounting problem somewhere in htree. Chris came uo
with the below patch. Does it fix it for you?


fs/ext3/namei.c | 50 ++++++++++++++++++++++++++++----------------------
1 files changed, 28 insertions(+), 22 deletions(-)

--- 25/fs/ext3/namei.c~htree-fix Tue Nov 5 18:48:52 2002
+++ 25-akpm/fs/ext3/namei.c Tue Nov 5 18:48:52 2002
@@ -880,18 +880,18 @@ static struct buffer_head * ext3_dx_find
top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize -
EXT3_DIR_REC_LEN(0));
for (; de < top; de = ext3_next_entry(de))
- if (ext3_match (namelen, name, de)) {
- if (!ext3_check_dir_entry("ext3_find_entry",
- dir, de, bh,
- (block<<EXT3_BLOCK_SIZE_BITS(sb))
- +((char *)de - bh->b_data))) {
- brelse (bh);
- goto errout;
+ if (ext3_match (namelen, name, de)) {
+ if (!ext3_check_dir_entry("ext3_find_entry",
+ dir, de, bh,
+ (block<<EXT3_BLOCK_SIZE_BITS(sb))
+ +((char *)de - bh->b_data))) {
+ brelse (bh);
+ goto errout;
+ }
+ *res_dir = de;
+ dx_release (frames);
+ return bh;
}
- *res_dir = de;
- dx_release (frames);
- return bh;
- }
brelse (bh);
/* Check to see if we should continue to search */
retval = ext3_htree_next_block(dir, hash, frame,
@@ -1129,7 +1129,7 @@ errout:
*/
static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
struct inode *inode, struct ext3_dir_entry_2 *de,
- struct buffer_head * bh)
+ struct buffer_head * bh, int *buffull)
{
struct inode *dir = dentry->d_parent->d_inode;
const char *name = dentry->d_name.name;
@@ -1160,8 +1160,11 @@ static int add_dirent_to_buf(handle_t *h
de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
offset += rlen;
}
- if ((char *) de > top)
+ if ((char *) de > top) {
+ assert(buffull);
+ *buffull = 1;
return -ENOSPC;
+ }
}
BUFFER_TRACE(bh, "get_write_access");
err = ext3_journal_get_write_access(handle, bh);
@@ -1286,7 +1289,7 @@ static int make_indexed_dir(handle_t *ha
if (!(de))
return retval;

- return add_dirent_to_buf(handle, dentry, inode, de, bh);
+ return add_dirent_to_buf(handle, dentry, inode, de, bh, NULL);
}
#endif

@@ -1308,7 +1311,7 @@ static int ext3_add_entry (handle_t *han
struct buffer_head * bh;
struct ext3_dir_entry_2 *de;
struct super_block * sb;
- int retval;
+ int retval,buffull;
#ifdef CONFIG_EXT3_INDEX
int dx_fallback=0;
#endif
@@ -1335,8 +1338,10 @@ static int ext3_add_entry (handle_t *han
bh = ext3_bread(handle, dir, block, 0, &retval);
if(!bh)
return retval;
- retval = add_dirent_to_buf(handle, dentry, inode, 0, bh);
- if (retval != -ENOSPC)
+ buffull = 0;
+ retval = add_dirent_to_buf(handle, dentry, inode, 0, bh,
+ &buffull);
+ if (!buffull)
return retval;

#ifdef CONFIG_EXT3_INDEX
@@ -1353,7 +1358,7 @@ static int ext3_add_entry (handle_t *han
de->inode = 0;
de->rec_len = cpu_to_le16(rlen = blocksize);
nlen = 0;
- return add_dirent_to_buf(handle, dentry, inode, de, bh);
+ return add_dirent_to_buf(handle, dentry, inode, de, bh, NULL);
}

#ifdef CONFIG_EXT3_INDEX
@@ -1370,7 +1375,7 @@ static int ext3_dx_add_entry(handle_t *h
struct inode *dir = dentry->d_parent->d_inode;
struct super_block * sb = dir->i_sb;
struct ext3_dir_entry_2 *de;
- int err;
+ int err,buffull;

frame = dx_probe(dentry, 0, &hinfo, frames, &err);
if (!frame)
@@ -1386,8 +1391,9 @@ static int ext3_dx_add_entry(handle_t *h
if (err)
goto journal_error;

- err = add_dirent_to_buf(handle, dentry, inode, 0, bh);
- if (err != -ENOSPC) {
+ buffull = 0;
+ err = add_dirent_to_buf(handle, dentry, inode, 0, bh, &buffull);
+ if (!buffull) {
bh = 0;
goto cleanup;
}
@@ -1479,7 +1485,7 @@ static int ext3_dx_add_entry(handle_t *h
de = do_split(handle, dir, &bh, frame, &hinfo, &err);
if (!de)
goto cleanup;
- err = add_dirent_to_buf(handle, dentry, inode, de, bh);
+ err = add_dirent_to_buf(handle, dentry, inode, de, bh, NULL);
bh = 0;
goto cleanup;


_