Skip to content

Commit 0b310d9

Browse files
ryncsnakpm00
authored andcommitted
mm, swap: use cluster lock for HDD
Cluster lock (ci->lock) was introduced to reduce contention for certain operations. Using cluster lock for HDD is not helpful as HDD have a poor performance, so locking isn't the bottleneck. But having different set of locks for HDD / non-HDD prevents further rework of device lock (si->lock). This commit just changed all lock_cluster_or_swap_info to lock_cluster, which is a safe and straight conversion since cluster info is always allocated now, also removed all cluster_info related checks. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Kairui Song <[email protected]> Suggested-by: Chris Li <[email protected]> Reviewed-by: Baoquan He <[email protected]> Cc: Barry Song <[email protected]> Cc: "Huang, Ying" <[email protected]> Cc: Hugh Dickens <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Kalesh Singh <[email protected]> Cc: Nhat Pham <[email protected]> Cc: Ryan Roberts <[email protected]> Cc: Yosry Ahmed <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7277433 commit 0b310d9

File tree

1 file changed

+35
-74
lines changed

1 file changed

+35
-74
lines changed

mm/swapfile.c

Lines changed: 35 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,9 @@ static void swap_entry_range_free(struct swap_info_struct *si, swp_entry_t entry
5858
static void swap_range_alloc(struct swap_info_struct *si, unsigned long offset,
5959
unsigned int nr_entries);
6060
static bool folio_swapcache_freeable(struct folio *folio);
61-
static struct swap_cluster_info *lock_cluster_or_swap_info(
62-
struct swap_info_struct *si, unsigned long offset);
63-
static void unlock_cluster_or_swap_info(struct swap_info_struct *si,
64-
struct swap_cluster_info *ci);
61+
static struct swap_cluster_info *lock_cluster(struct swap_info_struct *si,
62+
unsigned long offset);
63+
static void unlock_cluster(struct swap_cluster_info *ci);
6564

6665
static DEFINE_SPINLOCK(swap_lock);
6766
static unsigned int nr_swapfiles;
@@ -222,9 +221,9 @@ static int __try_to_reclaim_swap(struct swap_info_struct *si,
222221
* swap_map is HAS_CACHE only, which means the slots have no page table
223222
* reference or pending writeback, and can't be allocated to others.
224223
*/
225-
ci = lock_cluster_or_swap_info(si, offset);
224+
ci = lock_cluster(si, offset);
226225
need_reclaim = swap_is_has_cache(si, offset, nr_pages);
227-
unlock_cluster_or_swap_info(si, ci);
226+
unlock_cluster(ci);
228227
if (!need_reclaim)
229228
goto out_unlock;
230229

@@ -404,45 +403,15 @@ static inline struct swap_cluster_info *lock_cluster(struct swap_info_struct *si
404403
{
405404
struct swap_cluster_info *ci;
406405

407-
ci = si->cluster_info;
408-
if (ci) {
409-
ci += offset / SWAPFILE_CLUSTER;
410-
spin_lock(&ci->lock);
411-
}
412-
return ci;
413-
}
414-
415-
static inline void unlock_cluster(struct swap_cluster_info *ci)
416-
{
417-
if (ci)
418-
spin_unlock(&ci->lock);
419-
}
420-
421-
/*
422-
* Determine the locking method in use for this device. Return
423-
* swap_cluster_info if SSD-style cluster-based locking is in place.
424-
*/
425-
static inline struct swap_cluster_info *lock_cluster_or_swap_info(
426-
struct swap_info_struct *si, unsigned long offset)
427-
{
428-
struct swap_cluster_info *ci;
429-
430-
/* Try to use fine-grained SSD-style locking if available: */
431-
ci = lock_cluster(si, offset);
432-
/* Otherwise, fall back to traditional, coarse locking: */
433-
if (!ci)
434-
spin_lock(&si->lock);
406+
ci = &si->cluster_info[offset / SWAPFILE_CLUSTER];
407+
spin_lock(&ci->lock);
435408

436409
return ci;
437410
}
438411

439-
static inline void unlock_cluster_or_swap_info(struct swap_info_struct *si,
440-
struct swap_cluster_info *ci)
412+
static inline void unlock_cluster(struct swap_cluster_info *ci)
441413
{
442-
if (ci)
443-
unlock_cluster(ci);
444-
else
445-
spin_unlock(&si->lock);
414+
spin_unlock(&ci->lock);
446415
}
447416

448417
/* Add a cluster to discard list and schedule it to do discard */
@@ -558,9 +527,6 @@ static void inc_cluster_info_page(struct swap_info_struct *si,
558527
unsigned long idx = page_nr / SWAPFILE_CLUSTER;
559528
struct swap_cluster_info *ci;
560529

561-
if (!cluster_info)
562-
return;
563-
564530
ci = cluster_info + idx;
565531
ci->count++;
566532

@@ -576,9 +542,6 @@ static void inc_cluster_info_page(struct swap_info_struct *si,
576542
static void dec_cluster_info_page(struct swap_info_struct *si,
577543
struct swap_cluster_info *ci, int nr_pages)
578544
{
579-
if (!si->cluster_info)
580-
return;
581-
582545
VM_BUG_ON(ci->count < nr_pages);
583546
VM_BUG_ON(cluster_is_free(ci));
584547
lockdep_assert_held(&si->lock);
@@ -940,7 +903,7 @@ static void swap_range_alloc(struct swap_info_struct *si, unsigned long offset,
940903
si->highest_bit = 0;
941904
del_from_avail_list(si);
942905

943-
if (si->cluster_info && vm_swap_full())
906+
if (vm_swap_full())
944907
schedule_work(&si->reclaim_work);
945908
}
946909
}
@@ -1007,8 +970,6 @@ static int cluster_alloc_swap(struct swap_info_struct *si,
1007970
{
1008971
int n_ret = 0;
1009972

1010-
VM_BUG_ON(!si->cluster_info);
1011-
1012973
si->flags += SWP_SCANNING;
1013974

1014975
while (n_ret < nr) {
@@ -1052,10 +1013,10 @@ static int scan_swap_map_slots(struct swap_info_struct *si,
10521013
}
10531014

10541015
/*
1055-
* Swapfile is not block device or not using clusters so unable
1016+
* Swapfile is not block device so unable
10561017
* to allocate large entries.
10571018
*/
1058-
if (!(si->flags & SWP_BLKDEV) || !si->cluster_info)
1019+
if (!(si->flags & SWP_BLKDEV))
10591020
return 0;
10601021
}
10611022

@@ -1295,9 +1256,9 @@ static unsigned char __swap_entry_free(struct swap_info_struct *si,
12951256
unsigned long offset = swp_offset(entry);
12961257
unsigned char usage;
12971258

1298-
ci = lock_cluster_or_swap_info(si, offset);
1259+
ci = lock_cluster(si, offset);
12991260
usage = __swap_entry_free_locked(si, offset, 1);
1300-
unlock_cluster_or_swap_info(si, ci);
1261+
unlock_cluster(ci);
13011262
if (!usage)
13021263
free_swap_slot(entry);
13031264

@@ -1320,14 +1281,14 @@ static bool __swap_entries_free(struct swap_info_struct *si,
13201281
if (nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER)
13211282
goto fallback;
13221283

1323-
ci = lock_cluster_or_swap_info(si, offset);
1284+
ci = lock_cluster(si, offset);
13241285
if (!swap_is_last_map(si, offset, nr, &has_cache)) {
1325-
unlock_cluster_or_swap_info(si, ci);
1286+
unlock_cluster(ci);
13261287
goto fallback;
13271288
}
13281289
for (i = 0; i < nr; i++)
13291290
WRITE_ONCE(si->swap_map[offset + i], SWAP_HAS_CACHE);
1330-
unlock_cluster_or_swap_info(si, ci);
1291+
unlock_cluster(ci);
13311292

13321293
if (!has_cache) {
13331294
for (i = 0; i < nr; i++)
@@ -1383,26 +1344,26 @@ static void cluster_swap_free_nr(struct swap_info_struct *si,
13831344
DECLARE_BITMAP(to_free, BITS_PER_LONG) = { 0 };
13841345
int i, nr;
13851346

1386-
ci = lock_cluster_or_swap_info(si, offset);
1347+
ci = lock_cluster(si, offset);
13871348
while (nr_pages) {
13881349
nr = min(BITS_PER_LONG, nr_pages);
13891350
for (i = 0; i < nr; i++) {
13901351
if (!__swap_entry_free_locked(si, offset + i, usage))
13911352
bitmap_set(to_free, i, 1);
13921353
}
13931354
if (!bitmap_empty(to_free, BITS_PER_LONG)) {
1394-
unlock_cluster_or_swap_info(si, ci);
1355+
unlock_cluster(ci);
13951356
for_each_set_bit(i, to_free, BITS_PER_LONG)
13961357
free_swap_slot(swp_entry(si->type, offset + i));
13971358
if (nr == nr_pages)
13981359
return;
13991360
bitmap_clear(to_free, 0, BITS_PER_LONG);
1400-
ci = lock_cluster_or_swap_info(si, offset);
1361+
ci = lock_cluster(si, offset);
14011362
}
14021363
offset += nr;
14031364
nr_pages -= nr;
14041365
}
1405-
unlock_cluster_or_swap_info(si, ci);
1366+
unlock_cluster(ci);
14061367
}
14071368

14081369
/*
@@ -1441,24 +1402,24 @@ void put_swap_folio(struct folio *folio, swp_entry_t entry)
14411402
if (!si)
14421403
return;
14431404

1444-
ci = lock_cluster_or_swap_info(si, offset);
1405+
ci = lock_cluster(si, offset);
14451406
if (size > 1 && swap_is_has_cache(si, offset, size)) {
1446-
unlock_cluster_or_swap_info(si, ci);
1407+
unlock_cluster(ci);
14471408
spin_lock(&si->lock);
14481409
swap_entry_range_free(si, entry, size);
14491410
spin_unlock(&si->lock);
14501411
return;
14511412
}
14521413
for (int i = 0; i < size; i++, entry.val++) {
14531414
if (!__swap_entry_free_locked(si, offset + i, SWAP_HAS_CACHE)) {
1454-
unlock_cluster_or_swap_info(si, ci);
1415+
unlock_cluster(ci);
14551416
free_swap_slot(entry);
14561417
if (i == size - 1)
14571418
return;
1458-
lock_cluster_or_swap_info(si, offset);
1419+
lock_cluster(si, offset);
14591420
}
14601421
}
1461-
unlock_cluster_or_swap_info(si, ci);
1422+
unlock_cluster(ci);
14621423
}
14631424

14641425
static int swp_entry_cmp(const void *ent1, const void *ent2)
@@ -1522,9 +1483,9 @@ int swap_swapcount(struct swap_info_struct *si, swp_entry_t entry)
15221483
struct swap_cluster_info *ci;
15231484
int count;
15241485

1525-
ci = lock_cluster_or_swap_info(si, offset);
1486+
ci = lock_cluster(si, offset);
15261487
count = swap_count(si->swap_map[offset]);
1527-
unlock_cluster_or_swap_info(si, ci);
1488+
unlock_cluster(ci);
15281489
return count;
15291490
}
15301491

@@ -1547,7 +1508,7 @@ int swp_swapcount(swp_entry_t entry)
15471508

15481509
offset = swp_offset(entry);
15491510

1550-
ci = lock_cluster_or_swap_info(si, offset);
1511+
ci = lock_cluster(si, offset);
15511512

15521513
count = swap_count(si->swap_map[offset]);
15531514
if (!(count & COUNT_CONTINUED))
@@ -1570,7 +1531,7 @@ int swp_swapcount(swp_entry_t entry)
15701531
n *= (SWAP_CONT_MAX + 1);
15711532
} while (tmp_count & COUNT_CONTINUED);
15721533
out:
1573-
unlock_cluster_or_swap_info(si, ci);
1534+
unlock_cluster(ci);
15741535
return count;
15751536
}
15761537

@@ -1585,8 +1546,8 @@ static bool swap_page_trans_huge_swapped(struct swap_info_struct *si,
15851546
int i;
15861547
bool ret = false;
15871548

1588-
ci = lock_cluster_or_swap_info(si, offset);
1589-
if (!ci || nr_pages == 1) {
1549+
ci = lock_cluster(si, offset);
1550+
if (nr_pages == 1) {
15901551
if (swap_count(map[roffset]))
15911552
ret = true;
15921553
goto unlock_out;
@@ -1598,7 +1559,7 @@ static bool swap_page_trans_huge_swapped(struct swap_info_struct *si,
15981559
}
15991560
}
16001561
unlock_out:
1601-
unlock_cluster_or_swap_info(si, ci);
1562+
unlock_cluster(ci);
16021563
return ret;
16031564
}
16041565

@@ -3428,7 +3389,7 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
34283389
offset = swp_offset(entry);
34293390
VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER);
34303391
VM_WARN_ON(usage == 1 && nr > 1);
3431-
ci = lock_cluster_or_swap_info(si, offset);
3392+
ci = lock_cluster(si, offset);
34323393

34333394
err = 0;
34343395
for (i = 0; i < nr; i++) {
@@ -3483,7 +3444,7 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage, int nr)
34833444
}
34843445

34853446
unlock_out:
3486-
unlock_cluster_or_swap_info(si, ci);
3447+
unlock_cluster(ci);
34873448
return err;
34883449
}
34893450

0 commit comments

Comments
 (0)