diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2009-12-10 11:36:27 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2009-12-23 07:44:12 -0500 |
commit | 39bc680a8160bb9d6743f7873b535d553ff61058 (patch) | |
tree | 6aac2c11b09870bffb877dcaf6ae44b34b56d4db /fs/ext4 | |
parent | d21cd8f163ac44b15c465aab7306db931c606908 (diff) |
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: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ddd0a9c87d9e..ab807963a614 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1816,19 +1816,17 @@ repeat: | |||
1816 | 1816 | ||
1817 | md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; | 1817 | md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks; |
1818 | total = md_needed + nrblocks; | 1818 | total = md_needed + nrblocks; |
1819 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1819 | 1820 | ||
1820 | /* | 1821 | /* |
1821 | * Make quota reservation here to prevent quota overflow | 1822 | * Make quota reservation here to prevent quota overflow |
1822 | * later. Real quota accounting is done at pages writeout | 1823 | * later. Real quota accounting is done at pages writeout |
1823 | * time. | 1824 | * time. |
1824 | */ | 1825 | */ |
1825 | if (vfs_dq_reserve_block(inode, total)) { | 1826 | if (vfs_dq_reserve_block(inode, total)) |
1826 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1827 | return -EDQUOT; | 1827 | return -EDQUOT; |
1828 | } | ||
1829 | 1828 | ||
1830 | if (ext4_claim_free_blocks(sbi, total)) { | 1829 | if (ext4_claim_free_blocks(sbi, total)) { |
1831 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1832 | vfs_dq_release_reservation_block(inode, total); | 1830 | vfs_dq_release_reservation_block(inode, total); |
1833 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { | 1831 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { |
1834 | yield(); | 1832 | yield(); |
@@ -1836,10 +1834,11 @@ repeat: | |||
1836 | } | 1834 | } |
1837 | return -ENOSPC; | 1835 | return -ENOSPC; |
1838 | } | 1836 | } |
1837 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1839 | EXT4_I(inode)->i_reserved_data_blocks += nrblocks; | 1838 | EXT4_I(inode)->i_reserved_data_blocks += nrblocks; |
1840 | EXT4_I(inode)->i_reserved_meta_blocks = mdblocks; | 1839 | EXT4_I(inode)->i_reserved_meta_blocks += md_needed; |
1841 | |||
1842 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 1840 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1841 | |||
1843 | return 0; /* success */ | 1842 | return 0; /* success */ |
1844 | } | 1843 | } |
1845 | 1844 | ||