Skip to content

Commit c229969

Browse files
committed
shmem: 16K on 4K hack
Signed-off-by: Asahi Lina <[email protected]>
1 parent 4e7b082 commit c229969

4 files changed

Lines changed: 31 additions & 11 deletions

File tree

drivers/gpu/drm/drm_gem.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ int drm_gem_object_init(struct drm_device *dev,
135135

136136
obj->filp = filp;
137137

138+
#ifdef CONFIG_ARM64_4K_PAGES
139+
filp->f_mapping->order = 2;
140+
#endif
138141
return 0;
139142
}
140143
EXPORT_SYMBOL(drm_gem_object_init);

fs/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
212212
mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);
213213
mapping->private_data = NULL;
214214
mapping->writeback_index = 0;
215+
mapping->order = 0;
215216
init_rwsem(&mapping->invalidate_lock);
216217
lockdep_set_class_and_name(&mapping->invalidate_lock,
217218
&sb->s_type->invalidate_lock_key,

include/linux/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ struct address_space {
460460
spinlock_t private_lock;
461461
struct list_head private_list;
462462
void *private_data;
463+
unsigned long order;
463464
} __attribute__((aligned(sizeof(long)))) __randomize_layout;
464465
/*
465466
* On most architectures that alignment is already the case; but

mm/shmem.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ static struct vfsmount *shm_mnt;
9292
/* Symlink up to this size is kmalloc'ed instead of using a swappable page */
9393
#define SHORT_SYMLINK_LEN 128
9494

95+
static const unsigned long shmem_base_nr(struct address_space *mapping) {
96+
return 1L << mapping->order;
97+
}
98+
9599
/*
96100
* shmem_fallocate communicates with shmem_fault or shmem_writepage via
97101
* inode->i_private (with i_rwsem making sure that it has only one user at
@@ -705,6 +709,7 @@ static int shmem_add_to_page_cache(struct folio *folio,
705709
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
706710
VM_BUG_ON_FOLIO(!folio_test_swapbacked(folio), folio);
707711
VM_BUG_ON(expected && folio_test_large(folio));
712+
VM_BUG_ON_FOLIO(folio_order(folio) < mapping->order, folio);
708713

709714
folio_ref_add(folio, nr);
710715
folio->mapping = mapping;
@@ -1367,7 +1372,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
13671372
* "force", drivers/gpu/drm/i915/gem/i915_gem_shmem.c gets huge pages,
13681373
* and its shmem_writeback() needs them to be split when swapping.
13691374
*/
1370-
if (folio_test_large(folio)) {
1375+
if (folio->mapping->order == 0 && folio_test_large(folio)) {
13711376
/* Ensure the subpages are still dirty */
13721377
folio_test_set_dirty(folio);
13731378
if (split_huge_page(page) < 0)
@@ -1573,10 +1578,16 @@ static struct folio *shmem_alloc_folio(gfp_t gfp,
15731578
struct shmem_inode_info *info, pgoff_t index)
15741579
{
15751580
struct vm_area_struct pvma;
1581+
struct address_space *mapping = info->vfs_inode.i_mapping;
1582+
pgoff_t hindex;
15761583
struct folio *folio;
15771584

1585+
hindex = round_down(index, shmem_base_nr(mapping));
1586+
WARN_ON(xa_find(&mapping->i_pages, &hindex, hindex + shmem_base_nr(mapping) - 1,
1587+
XA_PRESENT));
1588+
15781589
shmem_pseudo_vma_init(&pvma, info, index);
1579-
folio = vma_alloc_folio(gfp, 0, &pvma, 0, false);
1590+
folio = vma_alloc_folio(gfp, mapping->order, &pvma, 0, false);
15801591
shmem_pseudo_vma_destroy(&pvma);
15811592

15821593
return folio;
@@ -1586,13 +1597,14 @@ static struct folio *shmem_alloc_and_acct_folio(gfp_t gfp, struct inode *inode,
15861597
pgoff_t index, bool huge)
15871598
{
15881599
struct shmem_inode_info *info = SHMEM_I(inode);
1600+
struct address_space *mapping = info->vfs_inode.i_mapping;
15891601
struct folio *folio;
15901602
int nr;
15911603
int err = -ENOSPC;
15921604

15931605
if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
15941606
huge = false;
1595-
nr = huge ? HPAGE_PMD_NR : 1;
1607+
nr = huge ? HPAGE_PMD_NR : shmem_base_nr(mapping);
15961608

15971609
if (!shmem_inode_acct_block(inode, nr))
15981610
goto failed;
@@ -1638,6 +1650,7 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
16381650
swp_entry_t entry;
16391651
pgoff_t swap_index;
16401652
int error;
1653+
int nr = folio_nr_pages(*foliop);
16411654

16421655
old = *foliop;
16431656
entry = folio_swap_entry(old);
@@ -1649,12 +1662,13 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
16491662
* limit chance of success by further cpuset and node constraints.
16501663
*/
16511664
gfp &= ~GFP_CONSTRAINT_MASK;
1652-
VM_BUG_ON_FOLIO(folio_test_large(old), old);
16531665
new = shmem_alloc_folio(gfp, info, index);
16541666
if (!new)
16551667
return -ENOMEM;
16561668

1657-
folio_get(new);
1669+
VM_BUG_ON_FOLIO(nr != folio_nr_pages(new), old);
1670+
1671+
folio_ref_add(new, nr);
16581672
folio_copy(new, old);
16591673
flush_dcache_folio(new);
16601674

@@ -1672,10 +1686,10 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
16721686
error = shmem_replace_entry(swap_mapping, swap_index, old, new);
16731687
if (!error) {
16741688
mem_cgroup_migrate(old, new);
1675-
__lruvec_stat_mod_folio(new, NR_FILE_PAGES, 1);
1676-
__lruvec_stat_mod_folio(new, NR_SHMEM, 1);
1677-
__lruvec_stat_mod_folio(old, NR_FILE_PAGES, -1);
1678-
__lruvec_stat_mod_folio(old, NR_SHMEM, -1);
1689+
__lruvec_stat_mod_folio(new, NR_FILE_PAGES, nr);
1690+
__lruvec_stat_mod_folio(new, NR_SHMEM, nr);
1691+
__lruvec_stat_mod_folio(old, NR_FILE_PAGES, -nr);
1692+
__lruvec_stat_mod_folio(old, NR_SHMEM, -nr);
16791693
}
16801694
xa_unlock_irq(&swap_mapping->i_pages);
16811695

@@ -1695,7 +1709,7 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
16951709
old->private = NULL;
16961710

16971711
folio_unlock(old);
1698-
folio_put_refs(old, 2);
1712+
folio_put_refs(old, 1 + nr);
16991713
return error;
17001714
}
17011715

@@ -2459,13 +2473,14 @@ int shmem_mfill_atomic_pte(pmd_t *dst_pmd,
24592473
}
24602474

24612475
if (!*foliop) {
2476+
pgoff_t aligned = round_down(pgoff, shmem_base_nr(mapping));
24622477
ret = -ENOMEM;
24632478
folio = shmem_alloc_folio(gfp, info, pgoff);
24642479
if (!folio)
24652480
goto out_unacct_blocks;
24662481

24672482
if (uffd_flags_mode_is(flags, MFILL_ATOMIC_COPY)) {
2468-
page_kaddr = kmap_local_folio(folio, 0);
2483+
page_kaddr = kmap_local_folio(folio, pgoff - aligned);
24692484
/*
24702485
* The read mmap_lock is held here. Despite the
24712486
* mmap_lock being read recursive a deadlock is still

0 commit comments

Comments
 (0)