diff options
author | Eric Sandeen <sandeen@redhat.com> | 2010-05-16 11:00:00 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-05-16 11:00:00 -0400 |
commit | 72b8ab9dde211ea518ff27e631b2046ef90c29a2 (patch) | |
tree | f63fc1894bcc39c81060e2fd8b21bedd07a1e958 /fs/ext4/balloc.c | |
parent | 0e05842bc117ea70ceb979cca798fd026879951b (diff) |
ext4: don't use quota reservation for speculative metadata
Because we can badly over-reserve metadata when we
calculate worst-case, it complicates things for quota, since
we must reserve and then claim later, retry on EDQUOT, etc.
Quota is also a generally smaller pool than fs free blocks,
so this over-reservation hurts more, and more often.
I'm of the opinion that it's not the worst thing to allow
metadata to push a user slightly over quota. This simplifies
the code and avoids the false quota rejections that result
from worst-case speculation.
This patch stops the speculative quota-charging for
worst-case metadata requirements, and just charges quota
when the blocks are allocated at writeout. It also is
able to remove the try-again loop on EDQUOT.
This patch has been tested indirectly by running the xfstests
suite with a hack to mount & enable quota prior to the test.
I also did a more specific test of fragmenting freespace
and then doing a large delalloc write under quota; quota
stopped me at the right amount of file IO, and then the
writeout generated enough metadata (due to the fragmentation)
that it put me slightly over quota, as expected.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/balloc.c')
-rw-r--r-- | fs/ext4/balloc.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index d2f37a5516c7..95b7594c76f9 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -591,14 +591,15 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, | |||
591 | ret = ext4_mb_new_blocks(handle, &ar, errp); | 591 | ret = ext4_mb_new_blocks(handle, &ar, errp); |
592 | if (count) | 592 | if (count) |
593 | *count = ar.len; | 593 | *count = ar.len; |
594 | |||
595 | /* | 594 | /* |
596 | * Account for the allocated meta blocks | 595 | * Account for the allocated meta blocks. We will never |
596 | * fail EDQUOT for metdata, but we do account for it. | ||
597 | */ | 597 | */ |
598 | if (!(*errp) && EXT4_I(inode)->i_delalloc_reserved_flag) { | 598 | if (!(*errp) && EXT4_I(inode)->i_delalloc_reserved_flag) { |
599 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | 599 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); |
600 | EXT4_I(inode)->i_allocated_meta_blocks += ar.len; | 600 | EXT4_I(inode)->i_allocated_meta_blocks += ar.len; |
601 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 601 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
602 | dquot_alloc_block_nofail(inode, ar.len); | ||
602 | } | 603 | } |
603 | return ret; | 604 | return ret; |
604 | } | 605 | } |