diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2010-01-22 17:06:20 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-01-22 17:06:20 -0500 |
commit | 1db913823c0f8360fccbd24ca67eb073966a5ffd (patch) | |
tree | ec5f7be2cfa884b04ca3d26c2dee53283fe16ca7 /fs/ext4 | |
parent | 74d2e4f8d79ae0c4b6ec027958d5b18058662eea (diff) |
ext4: Handle -EDQUOT error on write
We need to release the journal before we do a write_inode. Otherwise
we could deadlock.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c818972c8302..60b3a19e9927 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1835,24 +1835,12 @@ repeat: | |||
1835 | * later. Real quota accounting is done at pages writeout | 1835 | * later. Real quota accounting is done at pages writeout |
1836 | * time. | 1836 | * time. |
1837 | */ | 1837 | */ |
1838 | if (vfs_dq_reserve_block(inode, md_needed + 1)) { | 1838 | if (vfs_dq_reserve_block(inode, md_needed + 1)) |
1839 | /* | ||
1840 | * We tend to badly over-estimate the amount of | ||
1841 | * metadata blocks which are needed, so if we have | ||
1842 | * reserved any metadata blocks, try to force out the | ||
1843 | * inode and see if we have any better luck. | ||
1844 | */ | ||
1845 | if (md_reserved && retries++ <= 3) | ||
1846 | goto retry; | ||
1847 | return -EDQUOT; | 1839 | return -EDQUOT; |
1848 | } | ||
1849 | 1840 | ||
1850 | if (ext4_claim_free_blocks(sbi, md_needed + 1)) { | 1841 | if (ext4_claim_free_blocks(sbi, md_needed + 1)) { |
1851 | vfs_dq_release_reservation_block(inode, md_needed + 1); | 1842 | vfs_dq_release_reservation_block(inode, md_needed + 1); |
1852 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { | 1843 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { |
1853 | retry: | ||
1854 | if (md_reserved) | ||
1855 | write_inode_now(inode, (retries == 3)); | ||
1856 | yield(); | 1844 | yield(); |
1857 | goto repeat; | 1845 | goto repeat; |
1858 | } | 1846 | } |
@@ -3032,7 +3020,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
3032 | loff_t pos, unsigned len, unsigned flags, | 3020 | loff_t pos, unsigned len, unsigned flags, |
3033 | struct page **pagep, void **fsdata) | 3021 | struct page **pagep, void **fsdata) |
3034 | { | 3022 | { |
3035 | int ret, retries = 0; | 3023 | int ret, retries = 0, quota_retries = 0; |
3036 | struct page *page; | 3024 | struct page *page; |
3037 | pgoff_t index; | 3025 | pgoff_t index; |
3038 | unsigned from, to; | 3026 | unsigned from, to; |
@@ -3091,6 +3079,22 @@ retry: | |||
3091 | 3079 | ||
3092 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 3080 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
3093 | goto retry; | 3081 | goto retry; |
3082 | |||
3083 | if ((ret == -EDQUOT) && | ||
3084 | EXT4_I(inode)->i_reserved_meta_blocks && | ||
3085 | (quota_retries++ < 3)) { | ||
3086 | /* | ||
3087 | * Since we often over-estimate the number of meta | ||
3088 | * data blocks required, we may sometimes get a | ||
3089 | * spurios out of quota error even though there would | ||
3090 | * be enough space once we write the data blocks and | ||
3091 | * find out how many meta data blocks were _really_ | ||
3092 | * required. So try forcing the inode write to see if | ||
3093 | * that helps. | ||
3094 | */ | ||
3095 | write_inode_now(inode, (quota_retries == 3)); | ||
3096 | goto retry; | ||
3097 | } | ||
3094 | out: | 3098 | out: |
3095 | return ret; | 3099 | return ret; |
3096 | } | 3100 | } |