Commit 70022da8 authored by Ye Bin's avatar Ye Bin Committed by Theodore Ts'o

ext4: fix dead loop in ext4_mb_new_blocks

As we test disk offline/online with running fsstress, we find fsstress
process is keeping running state.
kworker/u32:3-262   [004] ...1   140.787471: ext4_mb_discard_preallocations: dev 8,32 needed 114
....
kworker/u32:3-262   [004] ...1   140.787471: ext4_mb_discard_preallocations: dev 8,32 needed 114

ext4_mb_new_blocks
repeat:
        ext4_mb_discard_preallocations_should_retry(sb, ac, &seq)
                freed = ext4_mb_discard_preallocations
                        ext4_mb_discard_group_preallocations
                                this_cpu_inc(discard_pa_seq);
                ---> freed == 0
                seq_retry = ext4_get_discard_pa_seq_sum
                        for_each_possible_cpu(__cpu)
                                __seq += per_cpu(discard_pa_seq, __cpu);
                if (seq_retry != *seq) {
                        *seq = seq_retry;
                        ret = true;
                }

As we see seq_retry is sum of discard_pa_seq every cpu, if
ext4_mb_discard_group_preallocations return zero discard_pa_seq in this
cpu maybe increase one, so condition "seq_retry != *seq" have always
been met.
Ritesh Harjani suggest to in ext4_mb_discard_group_preallocations function we
only increase discard_pa_seq when there is some PA to free.

Fixes: 07b5b8e1 ("ext4: mballoc: introduce pcpu seqcnt for freeing PA to improve ENOSPC handling")
Signed-off-by: default avatarYe Bin <yebin10@huawei.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarRitesh Harjani <riteshh@linux.ibm.com>
Link: https://lore.kernel.org/r/20200916113859.1556397-3-yebin10@huawei.comSigned-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 0e6895ba
...@@ -4189,7 +4189,6 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, ...@@ -4189,7 +4189,6 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
INIT_LIST_HEAD(&list); INIT_LIST_HEAD(&list);
repeat: repeat:
ext4_lock_group(sb, group); ext4_lock_group(sb, group);
this_cpu_inc(discard_pa_seq);
list_for_each_entry_safe(pa, tmp, list_for_each_entry_safe(pa, tmp,
&grp->bb_prealloc_list, pa_group_list) { &grp->bb_prealloc_list, pa_group_list) {
spin_lock(&pa->pa_lock); spin_lock(&pa->pa_lock);
...@@ -4206,6 +4205,9 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, ...@@ -4206,6 +4205,9 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
/* seems this one can be freed ... */ /* seems this one can be freed ... */
ext4_mb_mark_pa_deleted(sb, pa); ext4_mb_mark_pa_deleted(sb, pa);
if (!free)
this_cpu_inc(discard_pa_seq);
/* we can trust pa_free ... */ /* we can trust pa_free ... */
free += pa->pa_free; free += pa->pa_free;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment