Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/shmem: fix potential dead loop in shmem_unuse()

If multi shmem_unuse() for different swap type is called concurrently, a
dead loop could occur as following:

shmem_unuse(typeA) shmem_unuse(typeB)
mutex_lock(&shmem_swaplist_mutex)
list_for_each_entry_safe(info, next, ...)
...
mutex_unlock(&shmem_swaplist_mutex)
/* info->swapped may drop to 0 */
shmem_unuse_inode(&info->vfs_inode, type)

mutex_lock(&shmem_swaplist_mutex)
list_for_each_entry(info, next, ...)
if (!info->swapped)
list_del_init(&info->swaplist)

...
mutex_unlock(&shmem_swaplist_mutex)

mutex_lock(&shmem_swaplist_mutex)
/* iterate with offlist entry and encounter a dead loop */
next = list_next_entry(info, swaplist);
...

Restart the iteration if the inode is already off shmem_swaplist list to
fix the issue.

Link: https://lkml.kernel.org/r/20250516170939.965736-4-shikemeng@huaweicloud.com
Fixes: b56a2d8af914 ("mm: rid swapoff of quadratic complexity")
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Kairui Song <kasong@tencent.com>
Cc: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Kemeng Shi and committed by
Andrew Morton
3f778ab1 594ec2ab

+6 -3
+6 -3
mm/shmem.c
··· 1505 1505 return 0; 1506 1506 1507 1507 mutex_lock(&shmem_swaplist_mutex); 1508 + start_over: 1508 1509 list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) { 1509 1510 if (!info->swapped) { 1510 1511 list_del_init(&info->swaplist); ··· 1524 1523 cond_resched(); 1525 1524 1526 1525 mutex_lock(&shmem_swaplist_mutex); 1527 - next = list_next_entry(info, swaplist); 1528 - if (!info->swapped) 1529 - list_del_init(&info->swaplist); 1530 1526 if (atomic_dec_and_test(&info->stop_eviction)) 1531 1527 wake_up_var(&info->stop_eviction); 1532 1528 if (error) 1533 1529 break; 1530 + if (list_empty(&info->swaplist)) 1531 + goto start_over; 1532 + next = list_next_entry(info, swaplist); 1533 + if (!info->swapped) 1534 + list_del_init(&info->swaplist); 1534 1535 } 1535 1536 mutex_unlock(&shmem_swaplist_mutex); 1536 1537