ext4: Fix buffer head reference leak in no-journal mode
We found a problem with buffer head reference leaks when using an ext4 partition without a journal. In particular, calls to ext4_forget() would not to a brelse() on the input buffer head, which will cause pages they belong to to not be reclaimable. Further investigation showed that all places where ext4_journal_forget() and ext4_journal_revoke() are called are subject to the same problem. The patch below changes __ext4_journal_forget/__ext4_journal_revoke to do an explicit release of the buffer head when the journal handle isn't valid. Signed-off-by: Curt Wohlgemuth <curtw@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
62e086be5d
commit
e6b5d30104
3 changed files with 8 additions and 4 deletions
|
@ -43,6 +43,8 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
|
|||
ext4_journal_abort_handle(where, __func__, bh,
|
||||
handle, err);
|
||||
}
|
||||
else
|
||||
brelse(bh);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -57,6 +59,8 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
|
|||
ext4_journal_abort_handle(where, __func__, bh,
|
||||
handle, err);
|
||||
}
|
||||
else
|
||||
brelse(bh);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,9 +131,11 @@ int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
|
|||
int __ext4_journal_get_write_access(const char *where, handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
|
||||
/* When called with an invalid handle, this will still do a put on the BH */
|
||||
int __ext4_journal_forget(const char *where, handle_t *handle,
|
||||
struct buffer_head *bh);
|
||||
|
||||
/* When called with an invalid handle, this will still do a put on the BH */
|
||||
int __ext4_journal_revoke(const char *where, handle_t *handle,
|
||||
ext4_fsblk_t blocknr, struct buffer_head *bh);
|
||||
|
||||
|
|
|
@ -78,16 +78,14 @@ static int ext4_inode_is_fast_symlink(struct inode *inode)
|
|||
* but there may still be a record of it in the journal, and that record
|
||||
* still needs to be revoked.
|
||||
*
|
||||
* If the handle isn't valid we're not journaling so there's nothing to do.
|
||||
* If the handle isn't valid we're not journaling, but we still need to
|
||||
* call into ext4_journal_revoke() to put the buffer head.
|
||||
*/
|
||||
int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
|
||||
struct buffer_head *bh, ext4_fsblk_t blocknr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!ext4_handle_valid(handle))
|
||||
return 0;
|
||||
|
||||
might_sleep();
|
||||
|
||||
BUFFER_TRACE(bh, "enter");
|
||||
|
|
Loading…
Reference in a new issue