Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39bc680a authored by Dmitry Monakhov's avatar Dmitry Monakhov Committed by Jan Kara
Browse files

ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)

Unlock i_block_reservation_lock before vfs_dq_reserve_block().
This patch fixes http://bugzilla.kernel.org/show_bug.cgi?id=14739



CC: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarDmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent d21cd8f1
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -1816,19 +1816,17 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)

	md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
	total = md_needed + nrblocks;
	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);

	/*
	 * Make quota reservation here to prevent quota overflow
	 * later. Real quota accounting is done at pages writeout
	 * time.
	 */
	if (vfs_dq_reserve_block(inode, total)) {
		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
	if (vfs_dq_reserve_block(inode, total))
		return -EDQUOT;
	}

	if (ext4_claim_free_blocks(sbi, total)) {
		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
		vfs_dq_release_reservation_block(inode, total);
		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
			yield();
@@ -1836,10 +1834,11 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
		}
		return -ENOSPC;
	}
	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
	EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
	EXT4_I(inode)->i_reserved_meta_blocks = mdblocks;

	EXT4_I(inode)->i_reserved_meta_blocks += md_needed;
	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);

	return 0;       /* success */
}