Skip to content

Commit e06a8c2

Browse files
Mathieu Othacehetytso
authored andcommitted
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 <[email protected]> Signed-off-by: Lukas Skupinski <[email protected]> Signed-off-by: Mathieu Othacehe <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent d5e9836 commit e06a8c2

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

fs/ext4/super.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,12 +3719,12 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
37193719
ret = 1;
37203720

37213721
if (!ret) {
3722-
start_time = ktime_get_real_ns();
3722+
start_time = ktime_get_ns();
37233723
ret = ext4_init_inode_table(sb, group,
37243724
elr->lr_timeout ? 0 : 1);
37253725
trace_ext4_lazy_itable_init(sb, group);
37263726
if (elr->lr_timeout == 0) {
3727-
elr->lr_timeout = nsecs_to_jiffies((ktime_get_real_ns() - start_time) *
3727+
elr->lr_timeout = nsecs_to_jiffies((ktime_get_ns() - start_time) *
37283728
EXT4_SB(elr->lr_super)->s_li_wait_mult);
37293729
}
37303730
elr->lr_next_sched = jiffies + elr->lr_timeout;
@@ -3784,8 +3784,9 @@ static int ext4_lazyinit_thread(void *arg)
37843784

37853785
cont_thread:
37863786
while (true) {
3787-
next_wakeup = MAX_JIFFY_OFFSET;
3787+
bool next_wakeup_initialized = false;
37883788

3789+
next_wakeup = 0;
37893790
mutex_lock(&eli->li_list_mtx);
37903791
if (list_empty(&eli->li_request_list)) {
37913792
mutex_unlock(&eli->li_list_mtx);
@@ -3798,8 +3799,11 @@ static int ext4_lazyinit_thread(void *arg)
37983799
lr_request);
37993800

38003801
if (time_before(jiffies, elr->lr_next_sched)) {
3801-
if (time_before(elr->lr_next_sched, next_wakeup))
3802+
if (!next_wakeup_initialized ||
3803+
time_before(elr->lr_next_sched, next_wakeup)) {
38023804
next_wakeup = elr->lr_next_sched;
3805+
next_wakeup_initialized = true;
3806+
}
38033807
continue;
38043808
}
38053809
if (down_read_trylock(&elr->lr_super->s_umount)) {
@@ -3827,16 +3831,18 @@ static int ext4_lazyinit_thread(void *arg)
38273831
elr->lr_next_sched = jiffies +
38283832
get_random_u32_below(EXT4_DEF_LI_MAX_START_DELAY * HZ);
38293833
}
3830-
if (time_before(elr->lr_next_sched, next_wakeup))
3834+
if (!next_wakeup_initialized ||
3835+
time_before(elr->lr_next_sched, next_wakeup)) {
38313836
next_wakeup = elr->lr_next_sched;
3837+
next_wakeup_initialized = true;
3838+
}
38323839
}
38333840
mutex_unlock(&eli->li_list_mtx);
38343841

38353842
try_to_freeze();
38363843

38373844
cur = jiffies;
3838-
if ((time_after_eq(cur, next_wakeup)) ||
3839-
(MAX_JIFFY_OFFSET == next_wakeup)) {
3845+
if (!next_wakeup_initialized || time_after_eq(cur, next_wakeup)) {
38403846
cond_resched();
38413847
continue;
38423848
}

0 commit comments

Comments
 (0)