* [PATCH 1/5] mm: shmem: avoid unpaired folio_unlock() in shmem_swapin_folio()
2025-05-14 16:50 [PATCH 0/5] Some random fixes and cleanup to shmem Kemeng Shi
@ 2025-05-14 16:50 ` Kemeng Shi
2025-05-14 8:51 ` Baolin Wang
2025-05-14 16:50 ` [PATCH 2/5] mm: shmem: add missing shmem_unacct_size() in __shmem_file_setup() Kemeng Shi
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-14 16:50 UTC (permalink / raw)
To: hughd, baolin.wang, akpm; +Cc: linux-mm, linux-kernel
If we get a folio from swap_cache_get_folio() successfully but encounter
a failure before the folio is locked, we will unlock the folio which was
not previously locked.
Put the folio and set it to NULL when a failure occurs before the folio
is locked to fix the issue.
Fixes: 058313515d5aa ("mm: shmem: fix potential data corruption during shmem swapin")
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
---
mm/shmem.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/shmem.c b/mm/shmem.c
index 99327c30507c..980fa15f393e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2335,6 +2335,8 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
*/
split_order = shmem_split_large_entry(inode, index, swap, gfp);
if (split_order < 0) {
+ folio_put(folio);
+ folio = NULL;
error = split_order;
goto failed;
}
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/5] mm: shmem: avoid unpaired folio_unlock() in shmem_swapin_folio()
2025-05-14 16:50 ` [PATCH 1/5] mm: shmem: avoid unpaired folio_unlock() in shmem_swapin_folio() Kemeng Shi
@ 2025-05-14 8:51 ` Baolin Wang
0 siblings, 0 replies; 14+ messages in thread
From: Baolin Wang @ 2025-05-14 8:51 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 00:50, Kemeng Shi wrote:
> If we get a folio from swap_cache_get_folio() successfully but encounter
> a failure before the folio is locked, we will unlock the folio which was
> not previously locked.
> Put the folio and set it to NULL when a failure occurs before the folio
> is locked to fix the issue.
>
> Fixes: 058313515d5aa ("mm: shmem: fix potential data corruption during shmem swapin")
> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
Good catch. LGTM.
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> ---
> mm/shmem.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 99327c30507c..980fa15f393e 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -2335,6 +2335,8 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
> */
> split_order = shmem_split_large_entry(inode, index, swap, gfp);
> if (split_order < 0) {
> + folio_put(folio);
> + folio = NULL;
> error = split_order;
> goto failed;
> }
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/5] mm: shmem: add missing shmem_unacct_size() in __shmem_file_setup()
2025-05-14 16:50 [PATCH 0/5] Some random fixes and cleanup to shmem Kemeng Shi
2025-05-14 16:50 ` [PATCH 1/5] mm: shmem: avoid unpaired folio_unlock() in shmem_swapin_folio() Kemeng Shi
@ 2025-05-14 16:50 ` Kemeng Shi
2025-05-14 8:53 ` Baolin Wang
2025-05-14 16:50 ` [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse() Kemeng Shi
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-14 16:50 UTC (permalink / raw)
To: hughd, baolin.wang, akpm; +Cc: linux-mm, linux-kernel
We will miss shmem_unacct_size() when is_idmapped_mnt() returns a failure.
Move is_idmapped_mnt() before shmem_acct_size() to fix the issue.
Fixes: 7a80e5b8c6fa7 ("shmem: support idmapped mounts for tmpfs")
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
---
mm/shmem.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 980fa15f393e..495e661eb8bb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -5812,12 +5812,12 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name,
if (size < 0 || size > MAX_LFS_FILESIZE)
return ERR_PTR(-EINVAL);
- if (shmem_acct_size(flags, size))
- return ERR_PTR(-ENOMEM);
-
if (is_idmapped_mnt(mnt))
return ERR_PTR(-EINVAL);
+ if (shmem_acct_size(flags, size))
+ return ERR_PTR(-ENOMEM);
+
inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
S_IFREG | S_IRWXUGO, 0, flags);
if (IS_ERR(inode)) {
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 2/5] mm: shmem: add missing shmem_unacct_size() in __shmem_file_setup()
2025-05-14 16:50 ` [PATCH 2/5] mm: shmem: add missing shmem_unacct_size() in __shmem_file_setup() Kemeng Shi
@ 2025-05-14 8:53 ` Baolin Wang
0 siblings, 0 replies; 14+ messages in thread
From: Baolin Wang @ 2025-05-14 8:53 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 00:50, Kemeng Shi wrote:
> We will miss shmem_unacct_size() when is_idmapped_mnt() returns a failure.
> Move is_idmapped_mnt() before shmem_acct_size() to fix the issue.
>
> Fixes: 7a80e5b8c6fa7 ("shmem: support idmapped mounts for tmpfs")
> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
LGTM.
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> ---
> mm/shmem.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 980fa15f393e..495e661eb8bb 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -5812,12 +5812,12 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name,
> if (size < 0 || size > MAX_LFS_FILESIZE)
> return ERR_PTR(-EINVAL);
>
> - if (shmem_acct_size(flags, size))
> - return ERR_PTR(-ENOMEM);
> -
> if (is_idmapped_mnt(mnt))
> return ERR_PTR(-EINVAL);
>
> + if (shmem_acct_size(flags, size))
> + return ERR_PTR(-ENOMEM);
> +
> inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL,
> S_IFREG | S_IRWXUGO, 0, flags);
> if (IS_ERR(inode)) {
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse()
2025-05-14 16:50 [PATCH 0/5] Some random fixes and cleanup to shmem Kemeng Shi
2025-05-14 16:50 ` [PATCH 1/5] mm: shmem: avoid unpaired folio_unlock() in shmem_swapin_folio() Kemeng Shi
2025-05-14 16:50 ` [PATCH 2/5] mm: shmem: add missing shmem_unacct_size() in __shmem_file_setup() Kemeng Shi
@ 2025-05-14 16:50 ` Kemeng Shi
2025-05-14 9:24 ` Baolin Wang
2025-05-14 16:50 ` [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage() Kemeng Shi
2025-05-14 16:50 ` [PATCH 5/5] mm/shmem: remove unneeded xa_is_value() check in shmem_unuse_swap_entries() Kemeng Shi
4 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-14 16:50 UTC (permalink / raw)
To: hughd, baolin.wang, akpm; +Cc: linux-mm, linux-kernel
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.
Fixes: b56a2d8af9147 ("mm: rid swapoff of quadratic complexity")
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
---
mm/shmem.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mm/shmem.c b/mm/shmem.c
index 495e661eb8bb..0fed94c2bc09 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1505,6 +1505,7 @@ int shmem_unuse(unsigned int type)
return 0;
mutex_lock(&shmem_swaplist_mutex);
+start_over:
list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) {
if (!info->swapped) {
list_del_init(&info->swaplist);
@@ -1530,6 +1531,8 @@ int shmem_unuse(unsigned int type)
wake_up_var(&info->stop_eviction);
if (error)
break;
+ if (list_empty(&info->swaplist))
+ goto start_over;
}
mutex_unlock(&shmem_swaplist_mutex);
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse()
2025-05-14 16:50 ` [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse() Kemeng Shi
@ 2025-05-14 9:24 ` Baolin Wang
2025-05-15 1:05 ` Kemeng Shi
0 siblings, 1 reply; 14+ messages in thread
From: Baolin Wang @ 2025-05-14 9:24 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 00:50, Kemeng Shi wrote:
> 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.
>
> Fixes: b56a2d8af9147 ("mm: rid swapoff of quadratic complexity")
> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
> ---
> mm/shmem.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 495e661eb8bb..0fed94c2bc09 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1505,6 +1505,7 @@ int shmem_unuse(unsigned int type)
> return 0;
>
> mutex_lock(&shmem_swaplist_mutex);
> +start_over:
> list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) {
> if (!info->swapped) {
> list_del_init(&info->swaplist);
> @@ -1530,6 +1531,8 @@ int shmem_unuse(unsigned int type)
next = list_next_entry(info, swaplist);
if (!info->swapped)
list_del_init(&info->swaplist);
if (atomic_dec_and_test(&info->stop_eviction))
wake_up_var(&info->stop_eviction);
We may still hit the list warning when calling list_del_init() for the
off-list info->swaplist? So I hope we can add a check for the possible
off-list:
diff --git a/mm/shmem.c b/mm/shmem.c
index 99327c30507c..f5ae5e2d6fb4 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1523,9 +1523,11 @@ int shmem_unuse(unsigned int type)
cond_resched();
mutex_lock(&shmem_swaplist_mutex);
- next = list_next_entry(info, swaplist);
- if (!info->swapped)
- list_del_init(&info->swaplist);
+ if (!list_empty(&info->swaplist)) {
+ next = list_next_entry(info, swaplist);
+ if (!info->swapped)
+ list_del_init(&info->swaplist);
+ }
if (atomic_dec_and_test(&info->stop_eviction))
wake_up_var(&info->stop_eviction);
if (error)
> wake_up_var(&info->stop_eviction);
> if (error)
> break;
> + if (list_empty(&info->swaplist))
> + goto start_over;
> }
> mutex_unlock(&shmem_swaplist_mutex);
>
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse()
2025-05-14 9:24 ` Baolin Wang
@ 2025-05-15 1:05 ` Kemeng Shi
2025-05-15 3:59 ` Baolin Wang
0 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-15 1:05 UTC (permalink / raw)
To: Baolin Wang, hughd, akpm; +Cc: linux-mm, linux-kernel
on 5/14/2025 5:24 PM, Baolin Wang wrote:
>
>
> On 2025/5/15 00:50, Kemeng Shi wrote:
>> 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.
>>
>> Fixes: b56a2d8af9147 ("mm: rid swapoff of quadratic complexity")
>> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
>> ---
>> mm/shmem.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/mm/shmem.c b/mm/shmem.c
>> index 495e661eb8bb..0fed94c2bc09 100644
>> --- a/mm/shmem.c
>> +++ b/mm/shmem.c
>> @@ -1505,6 +1505,7 @@ int shmem_unuse(unsigned int type)
>> return 0;
>> mutex_lock(&shmem_swaplist_mutex);
>> +start_over:
>> list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) {
>> if (!info->swapped) {
>> list_del_init(&info->swaplist);
>> @@ -1530,6 +1531,8 @@ int shmem_unuse(unsigned int type)
>
> next = list_next_entry(info, swaplist);
> if (!info->swapped)
> list_del_init(&info->swaplist);
> if (atomic_dec_and_test(&info->stop_eviction))
> wake_up_var(&info->stop_eviction);
>
> We may still hit the list warning when calling list_del_init() for the off-list info->swaplist? So I hope we can add a check for the possible off-list:
Hello,
When entry is taken off list, it will be initialized to a valid empty entry
with INIT_LIST_HEAD(). So it should be fine to call list_del_init() for
off-list entry.
Please correct me if I miss anything. Thanks!
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 99327c30507c..f5ae5e2d6fb4 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1523,9 +1523,11 @@ int shmem_unuse(unsigned int type)
> cond_resched();
>
> mutex_lock(&shmem_swaplist_mutex);
> - next = list_next_entry(info, swaplist);
> - if (!info->swapped)
> - list_del_init(&info->swaplist);
> + if (!list_empty(&info->swaplist)) {
> + next = list_next_entry(info, swaplist);
> + if (!info->swapped)
> + list_del_init(&info->swaplist);
> + }
> if (atomic_dec_and_test(&info->stop_eviction))
> wake_up_var(&info->stop_eviction);
> if (error)
>
>> wake_up_var(&info->stop_eviction);
>> if (error)
>> break;
>> + if (list_empty(&info->swaplist))
>> + goto start_over;
>> }
>> mutex_unlock(&shmem_swaplist_mutex);
>>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse()
2025-05-15 1:05 ` Kemeng Shi
@ 2025-05-15 3:59 ` Baolin Wang
0 siblings, 0 replies; 14+ messages in thread
From: Baolin Wang @ 2025-05-15 3:59 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 09:05, Kemeng Shi wrote:
>
>
> on 5/14/2025 5:24 PM, Baolin Wang wrote:
>>
>>
>> On 2025/5/15 00:50, Kemeng Shi wrote:
>>> 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.
>>>
>>> Fixes: b56a2d8af9147 ("mm: rid swapoff of quadratic complexity")
>>> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
>>> ---
>>> mm/shmem.c | 3 +++
>>> 1 file changed, 3 insertions(+)
>>>
>>> diff --git a/mm/shmem.c b/mm/shmem.c
>>> index 495e661eb8bb..0fed94c2bc09 100644
>>> --- a/mm/shmem.c
>>> +++ b/mm/shmem.c
>>> @@ -1505,6 +1505,7 @@ int shmem_unuse(unsigned int type)
>>> return 0;
>>> mutex_lock(&shmem_swaplist_mutex);
>>> +start_over:
>>> list_for_each_entry_safe(info, next, &shmem_swaplist, swaplist) {
>>> if (!info->swapped) {
>>> list_del_init(&info->swaplist);
>>> @@ -1530,6 +1531,8 @@ int shmem_unuse(unsigned int type)
>>
>> next = list_next_entry(info, swaplist);
>> if (!info->swapped)
>> list_del_init(&info->swaplist);
>> if (atomic_dec_and_test(&info->stop_eviction))
>> wake_up_var(&info->stop_eviction);
>>
>> We may still hit the list warning when calling list_del_init() for the off-list info->swaplist? So I hope we can add a check for the possible off-list:
> Hello,
> When entry is taken off list, it will be initialized to a valid empty entry
> with INIT_LIST_HEAD(). So it should be fine to call list_del_init() for
> off-list entry.
> Please correct me if I miss anything. Thanks!
Ah, yes. I got confused with list_del(), but I still think we should not
continue to operate on an off-list entry.
>> diff --git a/mm/shmem.c b/mm/shmem.c
>> index 99327c30507c..f5ae5e2d6fb4 100644
>> --- a/mm/shmem.c
>> +++ b/mm/shmem.c
>> @@ -1523,9 +1523,11 @@ int shmem_unuse(unsigned int type)
>> cond_resched();
>>
>> mutex_lock(&shmem_swaplist_mutex);
>> - next = list_next_entry(info, swaplist);
>> - if (!info->swapped)
>> - list_del_init(&info->swaplist);
>> + if (!list_empty(&info->swaplist)) {
>> + next = list_next_entry(info, swaplist);
>> + if (!info->swapped)
>> + list_del_init(&info->swaplist);
>> + }
>> if (atomic_dec_and_test(&info->stop_eviction))
>> wake_up_var(&info->stop_eviction);
>> if (error)
>>
>>> wake_up_var(&info->stop_eviction);
>>> if (error)
>>> break;
>>> + if (list_empty(&info->swaplist))
>>> + goto start_over;
>>> }
>>> mutex_unlock(&shmem_swaplist_mutex);
>>>
>>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage()
2025-05-14 16:50 [PATCH 0/5] Some random fixes and cleanup to shmem Kemeng Shi
` (2 preceding siblings ...)
2025-05-14 16:50 ` [PATCH 3/5] mm/shmem: Fix potential dead loop in shmem_unuse() Kemeng Shi
@ 2025-05-14 16:50 ` Kemeng Shi
2025-05-14 9:31 ` Baolin Wang
2025-05-14 16:50 ` [PATCH 5/5] mm/shmem: remove unneeded xa_is_value() check in shmem_unuse_swap_entries() Kemeng Shi
4 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-14 16:50 UTC (permalink / raw)
To: hughd, baolin.wang, akpm; +Cc: linux-mm, linux-kernel
Even if we fail to allocate a swap entry, the inode might have previously
allocated entry and we might take inode containing swap entry off swaplist.
As a result, try_to_unuse() may enter a potential dead loop to repeatedly
look for inode and clean it's swap entry.
Address this by keeping inode in swaplist even if we fail to allocate
swap entry as it does not pose significant problem to keep inode without
swap entry in swaplist.
Fixes: b487a2da3575b ("mm, swap: simplify folio swap allocation")
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
---
mm/shmem.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 0fed94c2bc09..dfd2f730833c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1651,8 +1651,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
BUG_ON(folio_mapped(folio));
return swap_writepage(&folio->page, wbc);
}
-
- list_del_init(&info->swaplist);
mutex_unlock(&shmem_swaplist_mutex);
if (nr_pages > 1)
goto try_split;
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage()
2025-05-14 16:50 ` [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage() Kemeng Shi
@ 2025-05-14 9:31 ` Baolin Wang
2025-05-15 1:09 ` Kemeng Shi
0 siblings, 1 reply; 14+ messages in thread
From: Baolin Wang @ 2025-05-14 9:31 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 00:50, Kemeng Shi wrote:
> Even if we fail to allocate a swap entry, the inode might have previously
> allocated entry and we might take inode containing swap entry off swaplist.
> As a result, try_to_unuse() may enter a potential dead loop to repeatedly
> look for inode and clean it's swap entry.
> Address this by keeping inode in swaplist even if we fail to allocate
> swap entry as it does not pose significant problem to keep inode without
> swap entry in swaplist.
>
> Fixes: b487a2da3575b ("mm, swap: simplify folio swap allocation")
> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
> ---
> mm/shmem.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 0fed94c2bc09..dfd2f730833c 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1651,8 +1651,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
> BUG_ON(folio_mapped(folio));
> return swap_writepage(&folio->page, wbc);
> }
> -
> - list_del_init(&info->swaplist);
If 'info->swapped' is 0, we can still remove it?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage()
2025-05-14 9:31 ` Baolin Wang
@ 2025-05-15 1:09 ` Kemeng Shi
0 siblings, 0 replies; 14+ messages in thread
From: Kemeng Shi @ 2025-05-15 1:09 UTC (permalink / raw)
To: Baolin Wang, hughd, akpm; +Cc: linux-mm, linux-kernel
on 5/14/2025 5:31 PM, Baolin Wang wrote:
>
>
> On 2025/5/15 00:50, Kemeng Shi wrote:
>> Even if we fail to allocate a swap entry, the inode might have previously
>> allocated entry and we might take inode containing swap entry off swaplist.
>> As a result, try_to_unuse() may enter a potential dead loop to repeatedly
>> look for inode and clean it's swap entry.
>> Address this by keeping inode in swaplist even if we fail to allocate
>> swap entry as it does not pose significant problem to keep inode without
>> swap entry in swaplist.
>>
>> Fixes: b487a2da3575b ("mm, swap: simplify folio swap allocation")
>> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
>> ---
>> mm/shmem.c | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/mm/shmem.c b/mm/shmem.c
>> index 0fed94c2bc09..dfd2f730833c 100644
>> --- a/mm/shmem.c
>> +++ b/mm/shmem.c
>> @@ -1651,8 +1651,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
>> BUG_ON(folio_mapped(folio));
>> return swap_writepage(&folio->page, wbc);
>> }
>> -
>> - list_del_init(&info->swaplist);
>
> If 'info->swapped' is 0, we can still remove it?
>
Sure, both approaches are acceptable to me: either keep it in list unconditionlly as it was done in old
behavior, or remove it if it's info->swapped is 0.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 5/5] mm/shmem: remove unneeded xa_is_value() check in shmem_unuse_swap_entries()
2025-05-14 16:50 [PATCH 0/5] Some random fixes and cleanup to shmem Kemeng Shi
` (3 preceding siblings ...)
2025-05-14 16:50 ` [PATCH 4/5] mm: shmem: keep inode in swaplist when failed to allocate swap entry in shmem_writepage() Kemeng Shi
@ 2025-05-14 16:50 ` Kemeng Shi
2025-05-14 9:31 ` Baolin Wang
4 siblings, 1 reply; 14+ messages in thread
From: Kemeng Shi @ 2025-05-14 16:50 UTC (permalink / raw)
To: hughd, baolin.wang, akpm; +Cc: linux-mm, linux-kernel
As only value entry will be added to fbatch in shmem_find_swap_entries(),
there is no need to do xa_is_value() check in shmem_unuse_swap_entries().
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
---
mm/shmem.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index dfd2f730833c..f1d45fcff5e8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1446,8 +1446,6 @@ static int shmem_unuse_swap_entries(struct inode *inode,
for (i = 0; i < folio_batch_count(fbatch); i++) {
struct folio *folio = fbatch->folios[i];
- if (!xa_is_value(folio))
- continue;
error = shmem_swapin_folio(inode, indices[i], &folio, SGP_CACHE,
mapping_gfp_mask(mapping), NULL, NULL);
if (error == 0) {
--
2.30.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 5/5] mm/shmem: remove unneeded xa_is_value() check in shmem_unuse_swap_entries()
2025-05-14 16:50 ` [PATCH 5/5] mm/shmem: remove unneeded xa_is_value() check in shmem_unuse_swap_entries() Kemeng Shi
@ 2025-05-14 9:31 ` Baolin Wang
0 siblings, 0 replies; 14+ messages in thread
From: Baolin Wang @ 2025-05-14 9:31 UTC (permalink / raw)
To: Kemeng Shi, hughd, akpm; +Cc: linux-mm, linux-kernel
On 2025/5/15 00:50, Kemeng Shi wrote:
> As only value entry will be added to fbatch in shmem_find_swap_entries(),
> there is no need to do xa_is_value() check in shmem_unuse_swap_entries().
>
> Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
LGTM.
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> ---
> mm/shmem.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index dfd2f730833c..f1d45fcff5e8 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1446,8 +1446,6 @@ static int shmem_unuse_swap_entries(struct inode *inode,
> for (i = 0; i < folio_batch_count(fbatch); i++) {
> struct folio *folio = fbatch->folios[i];
>
> - if (!xa_is_value(folio))
> - continue;
> error = shmem_swapin_folio(inode, indices[i], &folio, SGP_CACHE,
> mapping_gfp_mask(mapping), NULL, NULL);
> if (error == 0) {
^ permalink raw reply [flat|nested] 14+ messages in thread