ext4: More buffer head reference leaks
After the patch I posted last week regarding buffer head ref leaks in no-journal mode, I looked at all the code that uses buffer heads and searched for more potential leaks. The patch below fixes the issues I found; these can occur even when a journal is present. The change to inode.c fixes a double release if ext4_journal_get_create_access() fails. The changes to namei.c are more complicated. add_dirent_to_buf() will release the input buffer head EXCEPT when it returns -ENOSPC. There are some callers of this routine that don't always do the brelse() in the event that -ENOSPC is returned. Unfortunately, to put this fix into ext4_add_entry() required capturing the return value of make_indexed_dir() and add_dirent_to_buf(). Signed-off-by: Curt Wohlgemuth <curtw@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
f6f50e28f0
commit
6487a9d3b5
@ -762,8 +762,9 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
|
||||
BUFFER_TRACE(bh, "call get_create_access");
|
||||
err = ext4_journal_get_create_access(handle, bh);
|
||||
if (err) {
|
||||
/* Don't brelse(bh) here; it's done in
|
||||
* ext4_journal_forget() below */
|
||||
unlock_buffer(bh);
|
||||
brelse(bh);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
@ -1518,8 +1518,12 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
return retval;
|
||||
|
||||
if (blocks == 1 && !dx_fallback &&
|
||||
EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
|
||||
return make_indexed_dir(handle, dentry, inode, bh);
|
||||
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;
|
||||
}
|
||||
brelse(bh);
|
||||
}
|
||||
bh = ext4_append(handle, dir, &block, &retval);
|
||||
@ -1528,7 +1532,10 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
de = (struct ext4_dir_entry_2 *) bh->b_data;
|
||||
de->inode = 0;
|
||||
de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
|
||||
return add_dirent_to_buf(handle, dentry, inode, de, bh);
|
||||
retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
|
||||
if (retval == -ENOSPC)
|
||||
brelse(bh);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1657,7 +1664,8 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
|
||||
if (!de)
|
||||
goto cleanup;
|
||||
err = add_dirent_to_buf(handle, dentry, inode, de, bh);
|
||||
bh = NULL;
|
||||
if (err != -ENOSPC)
|
||||
bh = NULL;
|
||||
goto cleanup;
|
||||
|
||||
journal_error:
|
||||
|
Loading…
Reference in New Issue
Block a user