--- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/mballoc.h
+++ linux-4.18.0-80.1.2.el8_0/fs/ext4/mballoc.h
-@@ -131,6 +131,7 @@ enum SHIFT_DIRECTION {
+@@ -131,6 +131,8 @@ enum SHIFT_DIRECTION {
ext4_lblk_t pa_lstart; /* log. block */
ext4_grpblk_t pa_len; /* len of preallocated chunk */
ext4_grpblk_t pa_free; /* how many blocks are free */
+ ext4_grpblk_t pa_group;
++ unsigned short pa_regular;
unsigned short pa_type; /* pa type. inode or group */
unsigned short pa_error;
spinlock_t *pa_obj_lock;
if (flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
--- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/mballoc.c
+++ linux-4.18.0-80.1.2.el8_0/fs/ext4/mballoc.c
-@@ -4267,6 +4291,21 @@ ext4_mb_use_inode_pa(struct ext4
+@@ -4267,6 +4291,25 @@ ext4_mb_use_inode_pa(struct ext4
ext4_fsblk_t end;
int len;
-+ if (ac->ac_flags & EXT4_MB_VERY_DENSE) {
++ if (ac->ac_flags & EXT4_MB_VERY_DENSE && !pa->pa_regular) {
+ unsigned int len = ac->ac_o_ex.fe_len;
++ if (len > pa->pa_free)
++ len = pa->pa_free;
+ ext4_get_group_no_and_offset(ac->ac_sb,
+ pa->pa_pstart,
+ &ac->ac_b_ex.fe_group,
+ &ac->ac_b_ex.fe_start);
+ ac->ac_b_ex.fe_len = len;
++ pa->pa_lstart += len;
+ pa->pa_pstart += len;
+ pa->pa_free -= len;
+ pa->pa_len -= len;
+ return;
+ }
+
++ pa->pa_regular = 1;
/* found preallocated blocks, use them */
start = pa->pa_pstart + (ac->ac_o_ex.fe_logical - pa->pa_lstart);
end = min(pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len),
-@@ -4367,6 +4380,24 @@ ext4_mb_use_preallocated(struct ext4
+@@ -4367,6 +4380,23 @@ ext4_mb_use_preallocated(struct ext4
if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
return false;
+ if (ac->ac_flags & EXT4_MB_VERY_DENSE) {
-+ unsigned int len = ac->ac_o_ex.fe_len;
+ rcu_read_lock();
+ list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
+ spin_lock(&pa->pa_lock);
-+ if (pa->pa_deleted == 0 && len <= pa->pa_free) {
++ if (!pa->pa_deleted && pa->pa_free && !pa->pa_regular) {
+ atomic_inc(&pa->pa_count);
+ ext4_mb_use_inode_pa(ac, pa);
+ spin_unlock(&pa->pa_lock);
/*
* possible race:
-@@ -4894,6 +4894,7 @@ ext4_mb_new_inode_pa(struct ext4
+@@ -4894,6 +4894,8 @@ ext4_mb_new_inode_pa(struct ext4
pa->pa_pstart = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
pa->pa_len = ac->ac_b_ex.fe_len;
pa->pa_free = pa->pa_len;
+ pa->pa_group = ac->ac_b_ex.fe_group;
++ pa->pa_regular = 0;
spin_lock_init(&pa->pa_lock);
INIT_LIST_HEAD(&pa->pa_inode_list);
INIT_LIST_HEAD(&pa->pa_group_list);