mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
ext4: prevent an infinite loop in the lazyinit thread
Use ktime_get_ns instead of ktime_get_real_ns when computing the lr_timeout not to be affected by system time jumps. Use a boolean instead of the MAX_JIFFY_OFFSET value to determine whether the next_wakeup value has been set. Comparing elr->lr_next_sched to MAX_JIFFY_OFFSET can cause the lazyinit thread to loop indefinitely. Co-developed-by: Lukas Skupinski <lukas.skupinski@landisgyr.com> Signed-off-by: Lukas Skupinski <lukas.skupinski@landisgyr.com> Signed-off-by: Mathieu Othacehe <othacehe@gnu.org> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20241106134741.26948-2-othacehe@gnu.org Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
d5e9836e13
commit
e06a8c24f6
@ -3719,12 +3719,12 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
|
||||
ret = 1;
|
||||
|
||||
if (!ret) {
|
||||
start_time = ktime_get_real_ns();
|
||||
start_time = ktime_get_ns();
|
||||
ret = ext4_init_inode_table(sb, group,
|
||||
elr->lr_timeout ? 0 : 1);
|
||||
trace_ext4_lazy_itable_init(sb, group);
|
||||
if (elr->lr_timeout == 0) {
|
||||
elr->lr_timeout = nsecs_to_jiffies((ktime_get_real_ns() - start_time) *
|
||||
elr->lr_timeout = nsecs_to_jiffies((ktime_get_ns() - start_time) *
|
||||
EXT4_SB(elr->lr_super)->s_li_wait_mult);
|
||||
}
|
||||
elr->lr_next_sched = jiffies + elr->lr_timeout;
|
||||
@ -3784,8 +3784,9 @@ static int ext4_lazyinit_thread(void *arg)
|
||||
|
||||
cont_thread:
|
||||
while (true) {
|
||||
next_wakeup = MAX_JIFFY_OFFSET;
|
||||
bool next_wakeup_initialized = false;
|
||||
|
||||
next_wakeup = 0;
|
||||
mutex_lock(&eli->li_list_mtx);
|
||||
if (list_empty(&eli->li_request_list)) {
|
||||
mutex_unlock(&eli->li_list_mtx);
|
||||
@ -3798,8 +3799,11 @@ static int ext4_lazyinit_thread(void *arg)
|
||||
lr_request);
|
||||
|
||||
if (time_before(jiffies, elr->lr_next_sched)) {
|
||||
if (time_before(elr->lr_next_sched, next_wakeup))
|
||||
if (!next_wakeup_initialized ||
|
||||
time_before(elr->lr_next_sched, next_wakeup)) {
|
||||
next_wakeup = elr->lr_next_sched;
|
||||
next_wakeup_initialized = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (down_read_trylock(&elr->lr_super->s_umount)) {
|
||||
@ -3827,16 +3831,18 @@ static int ext4_lazyinit_thread(void *arg)
|
||||
elr->lr_next_sched = jiffies +
|
||||
get_random_u32_below(EXT4_DEF_LI_MAX_START_DELAY * HZ);
|
||||
}
|
||||
if (time_before(elr->lr_next_sched, next_wakeup))
|
||||
if (!next_wakeup_initialized ||
|
||||
time_before(elr->lr_next_sched, next_wakeup)) {
|
||||
next_wakeup = elr->lr_next_sched;
|
||||
next_wakeup_initialized = true;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&eli->li_list_mtx);
|
||||
|
||||
try_to_freeze();
|
||||
|
||||
cur = jiffies;
|
||||
if ((time_after_eq(cur, next_wakeup)) ||
|
||||
(MAX_JIFFY_OFFSET == next_wakeup)) {
|
||||
if (!next_wakeup_initialized || time_after_eq(cur, next_wakeup)) {
|
||||
cond_resched();
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user