This is a partial revert of commit
6487a9d (only the changes made to
fs/ext4/namei.c), since it is causing the following brelse()
double-free warning when running fsstress on a file system with 1k
blocksize and we run into a block allocation failure while converting
a single-block directory to a multi-block hash-tree indexed directory.
WARNING: at fs/buffer.c:1197 __brelse+0x2e/0x33()
Hardware name:
VFS: brelse: Trying to free free buffer
Modules linked in:
Pid: 2226, comm: jbd2/sdd-8 Not tainted
2.6.32-rc6-00577-g0003f55 #101
Call Trace:
[<
c01587fb>] warn_slowpath_common+0x65/0x95
[<
c0158869>] warn_slowpath_fmt+0x29/0x2c
[<
c021168e>] __brelse+0x2e/0x33
[<
c0288a9f>] jbd2_journal_refile_buffer+0x67/0x6c
[<
c028a9ed>] jbd2_journal_commit_transaction+0x319/0x14d8
[<
c0164d73>] ? try_to_del_timer_sync+0x58/0x60
[<
c0175bcc>] ? sched_clock_cpu+0x12a/0x13e
[<
c017f6b4>] ? trace_hardirqs_off+0xb/0xd
[<
c0175c1f>] ? cpu_clock+0x3f/0x5b
[<
c017f6ec>] ? lock_release_holdtime+0x36/0x137
[<
c0664ad0>] ? _spin_unlock_irqrestore+0x44/0x51
[<
c0180af3>] ? trace_hardirqs_on_caller+0x103/0x124
[<
c0180b1f>] ? trace_hardirqs_on+0xb/0xd
[<
c0164d73>] ? try_to_del_timer_sync+0x58/0x60
[<
c0290d1c>] kjournald2+0x11a/0x310
[<
c017118e>] ? autoremove_wake_function+0x0/0x38
[<
c0290c02>] ? kjournald2+0x0/0x310
[<
c0170ee6>] kthread+0x66/0x6b
[<
c0170e80>] ? kthread+0x0/0x6b
[<
c01251b3>] kernel_thread_helper+0x7/0x10
---[ end trace
5579351b86af61e3 ]---
Commit
6487a9d was an attempt some buffer head leaks in an ENOSPC
error path, but in some cases it actually results in an excess ENOSPC,
as shown above. Fixing this means cleaning up who is responsible for
releasing the buffer heads from the callee to the caller of
add_dirent_to_buf().
Since that's a relatively complex change, and we're late in the rcX
development cycle, I'm reverting this now, and holding back a more
complete fix until after 2.6.32 ships. We've lived with this
buffer_head leak on ENOSPC in ext3 and ext4 for a very long time; a
few more months won't kill us.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Curt Wohlgemuth <curtw@google.com>
return retval;
if (blocks == 1 && !dx_fallback &&
- EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
- retval = make_indexed_dir(handle, dentry, inode, bh);
- if (retval == -ENOSPC)
- brelse(bh);
- return retval;
- }
+ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
+ return make_indexed_dir(handle, dentry, inode, bh);
brelse(bh);
}
bh = ext4_append(handle, dir, &block, &retval);
de = (struct ext4_dir_entry_2 *) bh->b_data;
de->inode = 0;
de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
- retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
- if (retval == -ENOSPC)
- brelse(bh);
- return retval;
+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
/*
if (!de)
goto cleanup;
err = add_dirent_to_buf(handle, dentry, inode, de, bh);
- if (err != -ENOSPC)
- bh = NULL;
+ bh = NULL;
goto cleanup;
journal_error: