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 | |
| 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>
| -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 | } |
