Commit d4a34d7f authored by Huang Ying's avatar Huang Ying Committed by Andrew Morton

mm,swap: add document about RCU read lock and swapoff interaction

During reviewing a patch to fix the race condition between
free_swap_and_cache() and swapoff() [1], it was found that the document
about how to prevent racing with swapoff isn't clear enough.  Especially
RCU read lock can prevent swapoff from freeing data structures.  So, the
document is added as comments.

[1] https://lore.kernel.org/linux-mm/c8fe62d0-78b8-527a-5bef-ee663ccdc37a@huawei.com/

Link: https://lkml.kernel.org/r/20240407065450.498821-1-ying.huang@intel.comSigned-off-by: default avatar"Huang, Ying" <ying.huang@intel.com>
Reviewed-by: default avatarRyan Roberts <ryan.roberts@arm.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarMiaohe Lin <linmiaohe@huawei.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 2bd9e6ee
...@@ -1238,16 +1238,15 @@ static unsigned char __swap_entry_free_locked(struct swap_info_struct *p, ...@@ -1238,16 +1238,15 @@ static unsigned char __swap_entry_free_locked(struct swap_info_struct *p,
/* /*
* When we get a swap entry, if there aren't some other ways to * When we get a swap entry, if there aren't some other ways to
* prevent swapoff, such as the folio in swap cache is locked, page * prevent swapoff, such as the folio in swap cache is locked, RCU
* table lock is held, etc., the swap entry may become invalid because * reader side is locked, etc., the swap entry may become invalid
* of swapoff. Then, we need to enclose all swap related functions * because of swapoff. Then, we need to enclose all swap related
* with get_swap_device() and put_swap_device(), unless the swap * functions with get_swap_device() and put_swap_device(), unless the
* functions call get/put_swap_device() by themselves. * swap functions call get/put_swap_device() by themselves.
* *
* Note that when only holding the PTL, swapoff might succeed immediately * RCU reader side lock (including any spinlock) is sufficient to
* after freeing a swap entry. Therefore, immediately after * prevent swapoff, because synchronize_rcu() is called in swapoff()
* __swap_entry_free(), the swap info might become stale and should not * before freeing data structures.
* be touched without a prior get_swap_device().
* *
* Check whether swap entry is valid in the swap device. If so, * Check whether swap entry is valid in the swap device. If so,
* return pointer to swap_info_struct, and keep the swap entry valid * return pointer to swap_info_struct, and keep the swap entry valid
...@@ -2544,10 +2543,11 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) ...@@ -2544,10 +2543,11 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
/* /*
* Wait for swap operations protected by get/put_swap_device() * Wait for swap operations protected by get/put_swap_device()
* to complete. * to complete. Because of synchronize_rcu() here, all swap
* * operations protected by RCU reader side lock (including any
* We need synchronize_rcu() here to protect the accessing to * spinlock) will be waited too. This makes it easy to
* the swap cache data structure. * prevent folio_test_swapcache() and the following swap cache
* operations from racing with swapoff.
*/ */
percpu_ref_kill(&p->users); percpu_ref_kill(&p->users);
synchronize_rcu(); synchronize_rcu();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment