All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Othacehe <othacehe@gnu.org>
To: Theodore Ts'o <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>
Cc: linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org,
	lukas.skupinski@landisgyr.com, anton.reding@landisgyr.com,
	Mathieu Othacehe <othacehe@gnu.org>
Subject: [PATCH 0/1] ext4: Prevent an infinite loop in the lazyinit thread.
Date: Wed,  6 Nov 2024 14:47:40 +0100	[thread overview]
Message-ID: <20241106134741.26948-1-othacehe@gnu.org> (raw)

Hello,

Under the following conditions, the lazyinit thread can reschedule itself
indefinitely without doing anything, consuming a large amount of the system
resources:

In the ext4_run_li_request function, a start_time timestamp is taken. Right
before elr->lr_timeout is computed, in the same function, the system clock is
updated in userspace, from the Unix Epoch to the current time. The
elr->lr_timeout takes a large value. The elr->lr_next_sched is then set to a
value far away in the future.

/*
 * Away from jiffies because of a time jump when computing
 * elr->lr_timeout.
 */
elr->lr_next_sched = jiffies + elr->lr_timeout;

Back, in the ext4_lazyinit_thread that called the ext4_run_li_request, the
following condition can be false:

// elr->lr_next_sched > next_wakeup
if (time_before(elr->lr_next_sched, next_wakeup))
        next_wakeup = elr->lr_next_sched;

so that next_wakeup is not updated. Assuming that next_wakeup was not updated
above and still has the MAX_JIFFY_OFFSET value, the following condition will
be true:

// next_wakeup == MAX_JIFFY_OFFSET
if ((time_after_eq(cur, next_wakeup)) ||
    (MAX_JIFFY_OFFSET == next_wakeup)) {
	cond_resched();
	continue;
}

causing us to process the li_request_list again. If we now have jiffies < 
elr->lr_next_sched, as we have already elr->lr_next_sched > next_wakeup, we
will just continue without updating next_wakeup,

// jiffies < elr->lr_next_sched && elr->lr_next_sched > next_wakeup
if (time_before(jiffies, elr->lr_next_sched)) {
	if (time_before(elr->lr_next_sched, next_wakeup))
		next_wakeup = elr->lr_next_sched;
	continue;
}

and again, we will call cond_resched because next_wakeup is not updated, and
we now have an infinite loop.

This was put into evidence with the following values:

jiffies = 4294938821
elr->lr_next_sched = 1966790060
next_wakeup = 1073741822 (MAX_JIFFY_OFFSET)

on an armv7 (32 bits) system, without an RTC, while updating the system clock
during the lazyinit thread is working.

Fix that by using ktime_get_ns insted of ktime_get_real_ns and by using a
boolean instead of MAX_JIFFY_OFFSET to determine whether the next_wakeup value
has been set.

Thanks,

Mathieu

Mathieu Othacehe (1):
  ext4: Prevent an infinite loop in the lazyinit thread.

 fs/ext4/super.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

-- 
2.46.0


             reply	other threads:[~2024-11-06 13:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-06 13:47 Mathieu Othacehe [this message]
2024-11-06 13:47 ` [PATCH 1/1] ext4: Prevent an infinite loop in the lazyinit thread Mathieu Othacehe
2024-11-08 10:49   ` Jan Kara
2024-11-14 13:53   ` Theodore Ts'o

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241106134741.26948-1-othacehe@gnu.org \
    --to=othacehe@gnu.org \
    --cc=adilger.kernel@dilger.ca \
    --cc=anton.reding@landisgyr.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas.skupinski@landisgyr.com \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.