diff options
author | Eric Whitney <enwlinux@gmail.com> | 2018-10-01 21:19:37 +0300 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2018-10-01 21:19:37 +0300 |
commit | 0b02f4c0d6d9e2c611dfbdd4317193e9dca740e6 (patch) | |
tree | a07c3e6aaad97caccc4e91214e8779b0a06bd901 /fs/ext4/extents_status.h | |
parent | 1dc0aa46e74a3366e12f426b7caaca477853e9c3 (diff) | |
download | linux-0b02f4c0d6d9e2c611dfbdd4317193e9dca740e6.tar.xz |
ext4: fix reserved cluster accounting at delayed write time
The code in ext4_da_map_blocks sometimes reserves space for more
delayed allocated clusters than it should, resulting in premature
ENOSPC, exceeded quota, and inaccurate free space reporting.
Fix this by checking for written and unwritten blocks shared in the
same cluster with the newly delayed allocated block. A cluster
reservation should not be made for a cluster for which physical space
has already been allocated.
Signed-off-by: Eric Whitney <enwlinux@gmail.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents_status.h')
-rw-r--r-- | fs/ext4/extents_status.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h index 379b7171c67c..9d3c676ec623 100644 --- a/fs/ext4/extents_status.h +++ b/fs/ext4/extents_status.h @@ -178,6 +178,16 @@ static inline int ext4_es_is_hole(struct extent_status *es) return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0; } +static inline int ext4_es_is_mapped(struct extent_status *es) +{ + return (ext4_es_is_written(es) || ext4_es_is_unwritten(es)); +} + +static inline int ext4_es_is_delonly(struct extent_status *es) +{ + return (ext4_es_is_delayed(es) && !ext4_es_is_unwritten(es)); +} + static inline void ext4_es_set_referenced(struct extent_status *es) { es->es_pblk |= ((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT; @@ -232,5 +242,7 @@ extern void ext4_exit_pending(void); extern void ext4_init_pending_tree(struct ext4_pending_tree *tree); extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk); extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk); +extern int ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, + bool allocated); #endif /* _EXT4_EXTENTS_STATUS_H */ |