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: swap: enable swap_entry_range_free() to drop any kind of last ref

The original VM_BUG_ON only allows swap_entry_range_free() to drop last
SWAP_HAS_CACHE ref. By allowing other kind of last ref in VM_BUG_ON,
swap_entry_range_free() could be a more general-purpose function able to
handle all kind of last ref. Following thi change, also rename
swap_entry_range_free() to swap_entries_free() and update it's comment
accordingly.

This is a preparation to use swap_entries_free() to drop more kind of last
ref other than SWAP_HAS_CACHE.

[shikemeng@huaweicloud.com: add __maybe_unused attribute for swap_is_last_ref() and update comment]
Link: https://lkml.kernel.org/r/20250410153908.612984-1-shikemeng@huaweicloud.com
Link: https://lkml.kernel.org/r/20250325162528.68385-3-shikemeng@huaweicloud.com
Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com>
Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
Reviewed-by: Baoquan He <bhe@redhat.com>
Tested-by: SeongJae Park <sj@kernel.org>
Cc: Kairui Song <kasong@tencent.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Kemeng Shi and committed by
Andrew Morton
64944ef6 9c1c38bc

+24 -14
+24 -14
mm/swapfile.c
··· 52 52 static bool swap_count_continued(struct swap_info_struct *, pgoff_t, 53 53 unsigned char); 54 54 static void free_swap_count_continuations(struct swap_info_struct *); 55 - static void swap_entry_range_free(struct swap_info_struct *si, 56 - struct swap_cluster_info *ci, 57 - swp_entry_t entry, unsigned int nr_pages); 55 + static void swap_entries_free(struct swap_info_struct *si, 56 + struct swap_cluster_info *ci, 57 + swp_entry_t entry, unsigned int nr_pages); 58 58 static void swap_range_alloc(struct swap_info_struct *si, 59 59 unsigned int nr_entries); 60 60 static bool folio_swapcache_freeable(struct folio *folio); ··· 1471 1471 ci = lock_cluster(si, offset); 1472 1472 usage = swap_entry_put_locked(si, offset, 1); 1473 1473 if (!usage) 1474 - swap_entry_range_free(si, ci, swp_entry(si->type, offset), 1); 1474 + swap_entries_free(si, ci, swp_entry(si->type, offset), 1); 1475 1475 unlock_cluster(ci); 1476 1476 1477 1477 return usage; ··· 1501 1501 for (i = 0; i < nr; i++) 1502 1502 WRITE_ONCE(si->swap_map[offset + i], SWAP_HAS_CACHE); 1503 1503 if (!has_cache) 1504 - swap_entry_range_free(si, ci, entry, nr); 1504 + swap_entries_free(si, ci, entry, nr); 1505 1505 unlock_cluster(ci); 1506 1506 1507 1507 return has_cache; ··· 1520 1520 } 1521 1521 1522 1522 /* 1523 - * Drop the last HAS_CACHE flag of swap entries, caller have to 1524 - * ensure all entries belong to the same cgroup. 1523 + * Check if it's the last ref of swap entry in the freeing path. 1524 + * Qualified vlaue includes 1, SWAP_HAS_CACHE or SWAP_MAP_SHMEM. 1525 1525 */ 1526 - static void swap_entry_range_free(struct swap_info_struct *si, 1527 - struct swap_cluster_info *ci, 1528 - swp_entry_t entry, unsigned int nr_pages) 1526 + static inline bool __maybe_unused swap_is_last_ref(unsigned char count) 1527 + { 1528 + return (count == SWAP_HAS_CACHE) || (count == 1) || 1529 + (count == SWAP_MAP_SHMEM); 1530 + } 1531 + 1532 + /* 1533 + * Drop the last ref of swap entries, caller have to ensure all entries 1534 + * belong to the same cgroup and cluster. 1535 + */ 1536 + static void swap_entries_free(struct swap_info_struct *si, 1537 + struct swap_cluster_info *ci, 1538 + swp_entry_t entry, unsigned int nr_pages) 1529 1539 { 1530 1540 unsigned long offset = swp_offset(entry); 1531 1541 unsigned char *map = si->swap_map + offset; ··· 1548 1538 1549 1539 ci->count -= nr_pages; 1550 1540 do { 1551 - VM_BUG_ON(*map != SWAP_HAS_CACHE); 1541 + VM_BUG_ON(!swap_is_last_ref(*map)); 1552 1542 *map = 0; 1553 1543 } while (++map < map_end); 1554 1544 ··· 1571 1561 ci = lock_cluster(si, offset); 1572 1562 do { 1573 1563 if (!swap_entry_put_locked(si, offset, usage)) 1574 - swap_entry_range_free(si, ci, swp_entry(si->type, offset), 1); 1564 + swap_entries_free(si, ci, swp_entry(si->type, offset), 1); 1575 1565 } while (++offset < end); 1576 1566 unlock_cluster(ci); 1577 1567 } ··· 1614 1604 1615 1605 ci = lock_cluster(si, offset); 1616 1606 if (swap_only_has_cache(si, offset, size)) 1617 - swap_entry_range_free(si, ci, entry, size); 1607 + swap_entries_free(si, ci, entry, size); 1618 1608 else { 1619 1609 for (int i = 0; i < size; i++, entry.val++) { 1620 1610 if (!swap_entry_put_locked(si, offset + i, SWAP_HAS_CACHE)) 1621 - swap_entry_range_free(si, ci, entry, 1); 1611 + swap_entries_free(si, ci, entry, 1); 1622 1612 } 1623 1613 } 1624 1614 unlock_cluster(ci);