Commit f4c2d372 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o

ext4: fix leak of quota reservations

Commit 8fcc3a58 ("ext4: rework reserved cluster accounting when
invalidating pages") moved freeing of delayed allocation reservations
from dirty page invalidation time to time when we evict corresponding
status extent from extent status tree. For inodes which don't have any
blocks allocated this may actually happen only in ext4_clear_blocks()
which is after we've dropped references to quota structures from the
inode. Thus reservation of quota leaked. Fix the problem by clearing
quota information from the inode only after evicting extent status tree
in ext4_clear_inode().

Link: https://lore.kernel.org/r/20191108115420.GI20863@quack2.suse.czReported-by: default avatarKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Fixes: 8fcc3a58 ("ext4: rework reserved cluster accounting when invalidating pages")
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 1e1a76ed
...@@ -265,13 +265,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) ...@@ -265,13 +265,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
ext4_debug("freeing inode %lu\n", ino); ext4_debug("freeing inode %lu\n", ino);
trace_ext4_free_inode(inode); trace_ext4_free_inode(inode);
/*
* Note: we must free any quota before locking the superblock,
* as writing the quota to disk may need the lock as well.
*/
dquot_initialize(inode); dquot_initialize(inode);
dquot_free_inode(inode); dquot_free_inode(inode);
dquot_drop(inode);
is_directory = S_ISDIR(inode->i_mode); is_directory = S_ISDIR(inode->i_mode);
......
...@@ -1172,9 +1172,9 @@ void ext4_clear_inode(struct inode *inode) ...@@ -1172,9 +1172,9 @@ void ext4_clear_inode(struct inode *inode)
{ {
invalidate_inode_buffers(inode); invalidate_inode_buffers(inode);
clear_inode(inode); clear_inode(inode);
dquot_drop(inode);
ext4_discard_preallocations(inode); ext4_discard_preallocations(inode);
ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
dquot_drop(inode);
if (EXT4_I(inode)->jinode) { if (EXT4_I(inode)->jinode) {
jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode), jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
EXT4_I(inode)->jinode); EXT4_I(inode)->jinode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment