diff options
author | Theodore Ts'o <tytso@mit.edu> | 2015-06-21 01:25:29 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2015-06-21 01:25:29 -0400 |
commit | c5e298ae53dc2eb69f2f7153be03454c8a33c658 (patch) | |
tree | 07bd2e74badcff3d55627b2f315b1640bbde15d8 /fs/ext4/inode.c | |
parent | 89d96a6f8e6491f24fc8f99fd6ae66820e85c6c1 (diff) |
ext4: prevent ext4_quota_write() from failing due to ENOSPC
In order to prevent quota block tracking to be inaccurate when
ext4_quota_write() fails with ENOSPC, we make two changes. The quota
file can now use the reserved block (since the quota file is arguably
file system metadata), and ext4_quota_write() now uses
ext4_should_retry_alloc() to retry the block allocation after a commit
has completed and released some blocks for allocation.
This fixes failures of xfstests generic/270:
Quota error (device vdc): write_blk: dquota write failed
Quota error (device vdc): qtree_write_dquot: Error -28 occurred while creating quota
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 263a46c488c7..e8a67b8ba90c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -731,18 +731,18 @@ int ext4_get_block(struct inode *inode, sector_t iblock, | |||
731 | * `handle' can be NULL if create is zero | 731 | * `handle' can be NULL if create is zero |
732 | */ | 732 | */ |
733 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | 733 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, |
734 | ext4_lblk_t block, int create) | 734 | ext4_lblk_t block, int map_flags) |
735 | { | 735 | { |
736 | struct ext4_map_blocks map; | 736 | struct ext4_map_blocks map; |
737 | struct buffer_head *bh; | 737 | struct buffer_head *bh; |
738 | int create = map_flags & EXT4_GET_BLOCKS_CREATE; | ||
738 | int err; | 739 | int err; |
739 | 740 | ||
740 | J_ASSERT(handle != NULL || create == 0); | 741 | J_ASSERT(handle != NULL || create == 0); |
741 | 742 | ||
742 | map.m_lblk = block; | 743 | map.m_lblk = block; |
743 | map.m_len = 1; | 744 | map.m_len = 1; |
744 | err = ext4_map_blocks(handle, inode, &map, | 745 | err = ext4_map_blocks(handle, inode, &map, map_flags); |
745 | create ? EXT4_GET_BLOCKS_CREATE : 0); | ||
746 | 746 | ||
747 | if (err == 0) | 747 | if (err == 0) |
748 | return create ? ERR_PTR(-ENOSPC) : NULL; | 748 | return create ? ERR_PTR(-ENOSPC) : NULL; |
@@ -788,11 +788,11 @@ errout: | |||
788 | } | 788 | } |
789 | 789 | ||
790 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, | 790 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, |
791 | ext4_lblk_t block, int create) | 791 | ext4_lblk_t block, int map_flags) |
792 | { | 792 | { |
793 | struct buffer_head *bh; | 793 | struct buffer_head *bh; |
794 | 794 | ||
795 | bh = ext4_getblk(handle, inode, block, create); | 795 | bh = ext4_getblk(handle, inode, block, map_flags); |
796 | if (IS_ERR(bh)) | 796 | if (IS_ERR(bh)) |
797 | return bh; | 797 | return bh; |
798 | if (!bh || buffer_uptodate(bh)) | 798 | if (!bh || buffer_uptodate(bh)) |