@@ -1288,30 +1288,29 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
1288
1288
*
1289
1289
* Basic scheme is simple, details are more complex:
1290
1290
* - allocate and freeze a new huge page;
1291
- * - scan over radix tree replacing old pages the new one
1291
+ * - scan page cache replacing old pages with the new one
1292
1292
* + swap in pages if necessary;
1293
1293
* + fill in gaps;
1294
- * + keep old pages around in case if rollback is required;
1295
- * - if replacing succeed :
1294
+ * + keep old pages around in case rollback is required;
1295
+ * - if replacing succeeds :
1296
1296
* + copy data over;
1297
1297
* + free old pages;
1298
1298
* + unfreeze huge page;
1299
1299
* - if replacing failed;
1300
1300
* + put all pages back and unfreeze them;
1301
- * + restore gaps in the radix-tree ;
1301
+ * + restore gaps in the page cache ;
1302
1302
* + free huge page;
1303
1303
*/
1304
1304
static void collapse_shmem (struct mm_struct * mm ,
1305
1305
struct address_space * mapping , pgoff_t start ,
1306
1306
struct page * * hpage , int node )
1307
1307
{
1308
1308
gfp_t gfp ;
1309
- struct page * page , * new_page , * tmp ;
1309
+ struct page * new_page ;
1310
1310
struct mem_cgroup * memcg ;
1311
1311
pgoff_t index , end = start + HPAGE_PMD_NR ;
1312
1312
LIST_HEAD (pagelist );
1313
- struct radix_tree_iter iter ;
1314
- void * * slot ;
1313
+ XA_STATE_ORDER (xas , & mapping -> i_pages , start , HPAGE_PMD_ORDER );
1315
1314
int nr_none = 0 , result = SCAN_SUCCEED ;
1316
1315
1317
1316
VM_BUG_ON (start & (HPAGE_PMD_NR - 1 ));
@@ -1336,48 +1335,49 @@ static void collapse_shmem(struct mm_struct *mm,
1336
1335
__SetPageLocked (new_page );
1337
1336
BUG_ON (!page_ref_freeze (new_page , 1 ));
1338
1337
1339
-
1340
1338
/*
1341
- * At this point the new_page is 'frozen' (page_count() is zero), locked
1342
- * and not up-to-date. It's safe to insert it into radix tree, because
1343
- * nobody would be able to map it or use it in other way until we
1344
- * unfreeze it.
1339
+ * At this point the new_page is 'frozen' (page_count() is zero),
1340
+ * locked and not up-to-date. It's safe to insert it into the page
1341
+ * cache, because nobody would be able to map it or use it in other
1342
+ * way until we unfreeze it.
1345
1343
*/
1346
1344
1347
- index = start ;
1348
- xa_lock_irq (& mapping -> i_pages );
1349
- radix_tree_for_each_slot (slot , & mapping -> i_pages , & iter , start ) {
1350
- int n = min (iter .index , end ) - index ;
1351
-
1352
- /*
1353
- * Handle holes in the radix tree: charge it from shmem and
1354
- * insert relevant subpage of new_page into the radix-tree.
1355
- */
1356
- if (n && !shmem_charge (mapping -> host , n )) {
1357
- result = SCAN_FAIL ;
1345
+ /* This will be less messy when we use multi-index entries */
1346
+ do {
1347
+ xas_lock_irq (& xas );
1348
+ xas_create_range (& xas );
1349
+ if (!xas_error (& xas ))
1358
1350
break ;
1359
- }
1360
- nr_none += n ;
1361
- for (; index < min (iter .index , end ); index ++ ) {
1362
- radix_tree_insert (& mapping -> i_pages , index ,
1363
- new_page + (index % HPAGE_PMD_NR ));
1364
- }
1351
+ xas_unlock_irq (& xas );
1352
+ if (!xas_nomem (& xas , GFP_KERNEL ))
1353
+ goto out ;
1354
+ } while (1 );
1365
1355
1366
- /* We are done. */
1367
- if (index >= end )
1368
- break ;
1356
+ xas_set (& xas , start );
1357
+ for (index = start ; index < end ; index ++ ) {
1358
+ struct page * page = xas_next (& xas );
1359
+
1360
+ VM_BUG_ON (index != xas .xa_index );
1361
+ if (!page ) {
1362
+ if (!shmem_charge (mapping -> host , 1 )) {
1363
+ result = SCAN_FAIL ;
1364
+ break ;
1365
+ }
1366
+ xas_store (& xas , new_page + (index % HPAGE_PMD_NR ));
1367
+ nr_none ++ ;
1368
+ continue ;
1369
+ }
1369
1370
1370
- page = radix_tree_deref_slot_protected (slot ,
1371
- & mapping -> i_pages .xa_lock );
1372
1371
if (xa_is_value (page ) || !PageUptodate (page )) {
1373
- xa_unlock_irq ( & mapping -> i_pages );
1372
+ xas_unlock_irq ( & xas );
1374
1373
/* swap in or instantiate fallocated page */
1375
1374
if (shmem_getpage (mapping -> host , index , & page ,
1376
1375
SGP_NOHUGE )) {
1377
1376
result = SCAN_FAIL ;
1378
- goto tree_unlocked ;
1377
+ goto xa_unlocked ;
1379
1378
}
1380
- xa_lock_irq (& mapping -> i_pages );
1379
+ xas_lock_irq (& xas );
1380
+ xas_set (& xas , index );
1381
1381
} else if (trylock_page (page )) {
1382
1382
get_page (page );
1383
1383
} else {
@@ -1397,7 +1397,7 @@ static void collapse_shmem(struct mm_struct *mm,
1397
1397
result = SCAN_TRUNCATED ;
1398
1398
goto out_unlock ;
1399
1399
}
1400
- xa_unlock_irq ( & mapping -> i_pages );
1400
+ xas_unlock_irq ( & xas );
1401
1401
1402
1402
if (isolate_lru_page (page )) {
1403
1403
result = SCAN_DEL_PAGE_LRU ;
@@ -1407,17 +1407,16 @@ static void collapse_shmem(struct mm_struct *mm,
1407
1407
if (page_mapped (page ))
1408
1408
unmap_mapping_pages (mapping , index , 1 , false);
1409
1409
1410
- xa_lock_irq (& mapping -> i_pages );
1410
+ xas_lock_irq (& xas );
1411
+ xas_set (& xas , index );
1411
1412
1412
- slot = radix_tree_lookup_slot (& mapping -> i_pages , index );
1413
- VM_BUG_ON_PAGE (page != radix_tree_deref_slot_protected (slot ,
1414
- & mapping -> i_pages .xa_lock ), page );
1413
+ VM_BUG_ON_PAGE (page != xas_load (& xas ), page );
1415
1414
VM_BUG_ON_PAGE (page_mapped (page ), page );
1416
1415
1417
1416
/*
1418
1417
* The page is expected to have page_count() == 3:
1419
1418
* - we hold a pin on it;
1420
- * - one reference from radix tree ;
1419
+ * - one reference from page cache ;
1421
1420
* - one from isolate_lru_page;
1422
1421
*/
1423
1422
if (!page_ref_freeze (page , 3 )) {
@@ -1432,56 +1431,30 @@ static void collapse_shmem(struct mm_struct *mm,
1432
1431
list_add_tail (& page -> lru , & pagelist );
1433
1432
1434
1433
/* Finally, replace with the new page. */
1435
- radix_tree_replace_slot (& mapping -> i_pages , slot ,
1436
- new_page + (index % HPAGE_PMD_NR ));
1437
-
1438
- slot = radix_tree_iter_resume (slot , & iter );
1439
- index ++ ;
1434
+ xas_store (& xas , new_page + (index % HPAGE_PMD_NR ));
1440
1435
continue ;
1441
1436
out_lru :
1442
- xa_unlock_irq ( & mapping -> i_pages );
1437
+ xas_unlock_irq ( & xas );
1443
1438
putback_lru_page (page );
1444
1439
out_isolate_failed :
1445
1440
unlock_page (page );
1446
1441
put_page (page );
1447
- goto tree_unlocked ;
1442
+ goto xa_unlocked ;
1448
1443
out_unlock :
1449
1444
unlock_page (page );
1450
1445
put_page (page );
1451
1446
break ;
1452
1447
}
1448
+ xas_unlock_irq (& xas );
1453
1449
1454
- /*
1455
- * Handle hole in radix tree at the end of the range.
1456
- * This code only triggers if there's nothing in radix tree
1457
- * beyond 'end'.
1458
- */
1459
- if (result == SCAN_SUCCEED && index < end ) {
1460
- int n = end - index ;
1461
-
1462
- if (!shmem_charge (mapping -> host , n )) {
1463
- result = SCAN_FAIL ;
1464
- goto tree_locked ;
1465
- }
1466
-
1467
- for (; index < end ; index ++ ) {
1468
- radix_tree_insert (& mapping -> i_pages , index ,
1469
- new_page + (index % HPAGE_PMD_NR ));
1470
- }
1471
- nr_none += n ;
1472
- }
1473
-
1474
- tree_locked :
1475
- xa_unlock_irq (& mapping -> i_pages );
1476
- tree_unlocked :
1477
-
1450
+ xa_unlocked :
1478
1451
if (result == SCAN_SUCCEED ) {
1479
- unsigned long flags ;
1452
+ struct page * page , * tmp ;
1480
1453
struct zone * zone = page_zone (new_page );
1481
1454
1482
1455
/*
1483
- * Replacing old pages with new one has succeed , now we need to
1484
- * copy the content and free old pages.
1456
+ * Replacing old pages with new one has succeeded , now we
1457
+ * need to copy the content and free the old pages.
1485
1458
*/
1486
1459
list_for_each_entry_safe (page , tmp , & pagelist , lru ) {
1487
1460
copy_highpage (new_page + (page -> index % HPAGE_PMD_NR ),
@@ -1495,16 +1468,16 @@ static void collapse_shmem(struct mm_struct *mm,
1495
1468
put_page (page );
1496
1469
}
1497
1470
1498
- local_irq_save ( flags );
1471
+ local_irq_disable ( );
1499
1472
__inc_node_page_state (new_page , NR_SHMEM_THPS );
1500
1473
if (nr_none ) {
1501
1474
__mod_node_page_state (zone -> zone_pgdat , NR_FILE_PAGES , nr_none );
1502
1475
__mod_node_page_state (zone -> zone_pgdat , NR_SHMEM , nr_none );
1503
1476
}
1504
- local_irq_restore ( flags );
1477
+ local_irq_enable ( );
1505
1478
1506
1479
/*
1507
- * Remove pte page tables, so we can re-faulti
1480
+ * Remove pte page tables, so we can re-fault
1508
1481
* the page as huge.
1509
1482
*/
1510
1483
retract_page_tables (mapping , start );
@@ -1521,37 +1494,37 @@ static void collapse_shmem(struct mm_struct *mm,
1521
1494
1522
1495
khugepaged_pages_collapsed ++ ;
1523
1496
} else {
1524
- /* Something went wrong: rollback changes to the radix-tree */
1497
+ struct page * page ;
1498
+ /* Something went wrong: roll back page cache changes */
1525
1499
shmem_uncharge (mapping -> host , nr_none );
1526
- xa_lock_irq (& mapping -> i_pages );
1527
- radix_tree_for_each_slot (slot , & mapping -> i_pages , & iter , start ) {
1528
- if (iter .index >= end )
1529
- break ;
1500
+ xas_lock_irq (& xas );
1501
+ xas_set (& xas , start );
1502
+ xas_for_each (& xas , page , end - 1 ) {
1530
1503
page = list_first_entry_or_null (& pagelist ,
1531
1504
struct page , lru );
1532
- if (!page || iter . index < page -> index ) {
1505
+ if (!page || xas . xa_index < page -> index ) {
1533
1506
if (!nr_none )
1534
1507
break ;
1535
1508
nr_none -- ;
1536
1509
/* Put holes back where they were */
1537
- radix_tree_delete ( & mapping -> i_pages , iter . index );
1510
+ xas_store ( & xas , NULL );
1538
1511
continue ;
1539
1512
}
1540
1513
1541
- VM_BUG_ON_PAGE (page -> index != iter . index , page );
1514
+ VM_BUG_ON_PAGE (page -> index != xas . xa_index , page );
1542
1515
1543
1516
/* Unfreeze the page. */
1544
1517
list_del (& page -> lru );
1545
1518
page_ref_unfreeze (page , 2 );
1546
- radix_tree_replace_slot ( & mapping -> i_pages , slot , page );
1547
- slot = radix_tree_iter_resume ( slot , & iter );
1548
- xa_unlock_irq ( & mapping -> i_pages );
1519
+ xas_store ( & xas , page );
1520
+ xas_pause ( & xas );
1521
+ xas_unlock_irq ( & xas );
1549
1522
putback_lru_page (page );
1550
1523
unlock_page (page );
1551
- xa_lock_irq ( & mapping -> i_pages );
1524
+ xas_lock_irq ( & xas );
1552
1525
}
1553
1526
VM_BUG_ON (nr_none );
1554
- xa_unlock_irq ( & mapping -> i_pages );
1527
+ xas_unlock_irq ( & xas );
1555
1528
1556
1529
/* Unfreeze new_page, caller would take care about freeing it */
1557
1530
page_ref_unfreeze (new_page , 1 );
0 commit comments