[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200910161753.GB17362@quack2.suse.cz>
Date: Thu, 10 Sep 2020 18:17:53 +0200
From: Jan Kara <jack@...e.cz>
To: Ye Bin <yebin10@...wei.com>
Cc: tytso@....edu, adilger.kernel@...ger.ca, jack@...e.com,
linux-ext4@...r.kernel.org, Ritesh Harjani <riteshh@...ux.ibm.com>
Subject: Re: [PATCH v3] ext4: Fix dead loop in ext4_mb_new_blocks
On Thu 10-09-20 17:12:52, Ye Bin wrote:
> 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.
> To Fix this problem, in ext4_mb_discard_group_preallocations function increase
> discard_pa_seq only when it found preallocation to discard.
>
> Fixes: 07b5b8e1ac40 ("ext4: mballoc: introduce pcpu seqcnt for freeing PA to improve ENOSPC handling")
> Signed-off-by: Ye Bin <yebin10@...wei.com>
Thanks for the patch. One comment below.
> ---
> fs/ext4/mballoc.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index f386fe62727d..fd55264dc3fe 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -4191,7 +4191,6 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
> INIT_LIST_HEAD(&list);
> repeat:
> ext4_lock_group(sb, group);
> - this_cpu_inc(discard_pa_seq);
> list_for_each_entry_safe(pa, tmp,
> &grp->bb_prealloc_list, pa_group_list) {
> spin_lock(&pa->pa_lock);
> @@ -4233,6 +4232,9 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
> goto out;
> }
>
> + /* only increase when find reallocation to discard */
> + this_cpu_inc(discard_pa_seq);
> +
This is a good place to increment the counter but I think you also need to
handle the case:
if (free < needed && busy) {
busy = 0;
ext4_unlock_group(sb, group);
cond_resched();
goto repeat;
}
We can unlock the group here after removing some preallocations and thus
other processes checking discard_pa_seq could miss we did this. In fact I
think the code is somewhat buggy here and we should also discard extents
accumulated on "list" so far before unlocking the group. Ritesh?
Honza
--
Jan Kara <jack@...e.com>
SUSE Labs, CR
Powered by blists - more mailing lists