Skip to content

Commit 15fb96a

Browse files
committed
Merge tag 'mm-stable-2023-05-03-16-22' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull more MM updates from Andrew Morton: - Some DAMON cleanups from Kefeng Wang - Some KSM work from David Hildenbrand, to make the PR_SET_MEMORY_MERGE ioctl's behavior more similar to KSM's behavior. [ Andrew called these "final", but I suspect we'll have a series fixing up the fact that the last commit in the dmapools series in the previous pull seems to have unintentionally just reverted all the other commits in the same series.. - Linus ] * tag 'mm-stable-2023-05-03-16-22' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm: hwpoison: coredump: support recovery from dump_user_range() mm/page_alloc: add some comments to explain the possible hole in __pageblock_pfn_to_page() mm/ksm: move disabling KSM from s390/gmap code to KSM code selftests/ksm: ksm_functional_tests: add prctl unmerge test mm/ksm: unmerge and clear VM_MERGEABLE when setting PR_SET_MEMORY_MERGE=0 mm/damon/paddr: fix missing folio_sz update in damon_pa_young() mm/damon/paddr: minor refactor of damon_pa_mark_accessed_or_deactivate() mm/damon/paddr: minor refactor of damon_pa_pageout()
2 parents 671e148 + 245f092 commit 15fb96a

10 files changed

Lines changed: 172 additions & 52 deletions

File tree

arch/s390/mm/gmap.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,30 +2585,12 @@ EXPORT_SYMBOL_GPL(s390_enable_sie);
25852585

25862586
int gmap_mark_unmergeable(void)
25872587
{
2588-
struct mm_struct *mm = current->mm;
2589-
struct vm_area_struct *vma;
2590-
unsigned long vm_flags;
2591-
int ret;
2592-
VMA_ITERATOR(vmi, mm, 0);
2593-
25942588
/*
25952589
* Make sure to disable KSM (if enabled for the whole process or
25962590
* individual VMAs). Note that nothing currently hinders user space
25972591
* from re-enabling it.
25982592
*/
2599-
clear_bit(MMF_VM_MERGE_ANY, &mm->flags);
2600-
2601-
for_each_vma(vmi, vma) {
2602-
/* Copy vm_flags to avoid partial modifications in ksm_madvise */
2603-
vm_flags = vma->vm_flags;
2604-
ret = ksm_madvise(vma, vma->vm_start, vma->vm_end,
2605-
MADV_UNMERGEABLE, &vm_flags);
2606-
if (ret)
2607-
return ret;
2608-
vm_flags_reset(vma, vm_flags);
2609-
}
2610-
mm->def_flags &= ~VM_MERGEABLE;
2611-
return 0;
2593+
return ksm_disable(current->mm);
26122594
}
26132595
EXPORT_SYMBOL_GPL(gmap_mark_unmergeable);
26142596

fs/coredump.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ static int dump_emit_page(struct coredump_params *cprm, struct page *page)
882882
pos = file->f_pos;
883883
bvec_set_page(&bvec, page, PAGE_SIZE, 0);
884884
iov_iter_bvec(&iter, ITER_SOURCE, &bvec, 1, PAGE_SIZE);
885+
iov_iter_set_copy_mc(&iter);
885886
n = __kernel_write_iter(cprm->file, &iter, &pos);
886887
if (n != PAGE_SIZE)
887888
return 0;

include/linux/ksm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
2121

2222
void ksm_add_vma(struct vm_area_struct *vma);
2323
int ksm_enable_merge_any(struct mm_struct *mm);
24+
int ksm_disable_merge_any(struct mm_struct *mm);
25+
int ksm_disable(struct mm_struct *mm);
2426

2527
int __ksm_enter(struct mm_struct *mm);
2628
void __ksm_exit(struct mm_struct *mm);
@@ -79,6 +81,11 @@ static inline void ksm_add_vma(struct vm_area_struct *vma)
7981
{
8082
}
8183

84+
static inline int ksm_disable(struct mm_struct *mm)
85+
{
86+
return 0;
87+
}
88+
8289
static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
8390
{
8491
return 0;

include/linux/uio.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct iov_iter_state {
4242

4343
struct iov_iter {
4444
u8 iter_type;
45+
bool copy_mc;
4546
bool nofault;
4647
bool data_source;
4748
bool user_backed;
@@ -256,8 +257,22 @@ size_t _copy_from_iter_flushcache(void *addr, size_t bytes, struct iov_iter *i);
256257

257258
#ifdef CONFIG_ARCH_HAS_COPY_MC
258259
size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
260+
static inline void iov_iter_set_copy_mc(struct iov_iter *i)
261+
{
262+
i->copy_mc = true;
263+
}
264+
265+
static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
266+
{
267+
return i->copy_mc;
268+
}
259269
#else
260270
#define _copy_mc_to_iter _copy_to_iter
271+
static inline void iov_iter_set_copy_mc(struct iov_iter *i) { }
272+
static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
273+
{
274+
return false;
275+
}
261276
#endif
262277

263278
size_t iov_iter_zero(size_t bytes, struct iov_iter *);
@@ -380,6 +395,7 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction,
380395
WARN_ON(direction & ~(READ | WRITE));
381396
*i = (struct iov_iter) {
382397
.iter_type = ITER_UBUF,
398+
.copy_mc = false,
383399
.user_backed = true,
384400
.data_source = direction,
385401
.ubuf = buf,

kernel/sys.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,16 +2695,10 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
26952695
if (mmap_write_lock_killable(me->mm))
26962696
return -EINTR;
26972697

2698-
if (arg2) {
2698+
if (arg2)
26992699
error = ksm_enable_merge_any(me->mm);
2700-
} else {
2701-
/*
2702-
* TODO: we might want disable KSM on all VMAs and
2703-
* trigger unsharing to completely disable KSM.
2704-
*/
2705-
clear_bit(MMF_VM_MERGE_ANY, &me->mm->flags);
2706-
error = 0;
2707-
}
2700+
else
2701+
error = ksm_disable_merge_any(me->mm);
27082702
mmap_write_unlock(me->mm);
27092703
break;
27102704
case PR_GET_MEMORY_MERGE:

lib/iov_iter.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
434434
WARN_ON(direction & ~(READ | WRITE));
435435
*i = (struct iov_iter) {
436436
.iter_type = ITER_IOVEC,
437+
.copy_mc = false,
437438
.nofault = false,
438439
.user_backed = true,
439440
.data_source = direction,
@@ -630,6 +631,14 @@ size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
630631
EXPORT_SYMBOL_GPL(_copy_mc_to_iter);
631632
#endif /* CONFIG_ARCH_HAS_COPY_MC */
632633

634+
static void *memcpy_from_iter(struct iov_iter *i, void *to, const void *from,
635+
size_t size)
636+
{
637+
if (iov_iter_is_copy_mc(i))
638+
return (void *)copy_mc_to_kernel(to, from, size);
639+
return memcpy(to, from, size);
640+
}
641+
633642
size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
634643
{
635644
if (WARN_ON_ONCE(!i->data_source))
@@ -639,7 +648,7 @@ size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
639648
might_fault();
640649
iterate_and_advance(i, bytes, base, len, off,
641650
copyin(addr + off, base, len),
642-
memcpy(addr + off, base, len)
651+
memcpy_from_iter(i, addr + off, base, len)
643652
)
644653

645654
return bytes;
@@ -862,7 +871,7 @@ size_t copy_page_from_iter_atomic(struct page *page, unsigned offset, size_t byt
862871
}
863872
iterate_and_advance(i, bytes, base, len, off,
864873
copyin(p + off, base, len),
865-
memcpy(p + off, base, len)
874+
memcpy_from_iter(i, p + off, base, len)
866875
)
867876
kunmap_atomic(kaddr);
868877
return bytes;
@@ -1043,6 +1052,7 @@ void iov_iter_kvec(struct iov_iter *i, unsigned int direction,
10431052
WARN_ON(direction & ~(READ | WRITE));
10441053
*i = (struct iov_iter){
10451054
.iter_type = ITER_KVEC,
1055+
.copy_mc = false,
10461056
.data_source = direction,
10471057
.kvec = kvec,
10481058
.nr_segs = nr_segs,
@@ -1059,6 +1069,7 @@ void iov_iter_bvec(struct iov_iter *i, unsigned int direction,
10591069
WARN_ON(direction & ~(READ | WRITE));
10601070
*i = (struct iov_iter){
10611071
.iter_type = ITER_BVEC,
1072+
.copy_mc = false,
10621073
.data_source = direction,
10631074
.bvec = bvec,
10641075
.nr_segs = nr_segs,
@@ -1105,6 +1116,7 @@ void iov_iter_xarray(struct iov_iter *i, unsigned int direction,
11051116
BUG_ON(direction & ~1);
11061117
*i = (struct iov_iter) {
11071118
.iter_type = ITER_XARRAY,
1119+
.copy_mc = false,
11081120
.data_source = direction,
11091121
.xarray = xarray,
11101122
.xarray_start = start,
@@ -1128,6 +1140,7 @@ void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count)
11281140
BUG_ON(direction != READ);
11291141
*i = (struct iov_iter){
11301142
.iter_type = ITER_DISCARD,
1143+
.copy_mc = false,
11311144
.data_source = false,
11321145
.count = count,
11331146
.iov_offset = 0

mm/damon/paddr.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,8 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
134134
}
135135

136136
need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
137-
if (need_lock && !folio_trylock(folio)) {
138-
folio_put(folio);
139-
return false;
140-
}
137+
if (need_lock && !folio_trylock(folio))
138+
goto out;
141139

142140
rmap_walk(folio, &rwc);
143141

@@ -238,21 +236,18 @@ static unsigned long damon_pa_pageout(struct damon_region *r, struct damos *s)
238236
if (!folio)
239237
continue;
240238

241-
if (damos_pa_filter_out(s, folio)) {
242-
folio_put(folio);
243-
continue;
244-
}
239+
if (damos_pa_filter_out(s, folio))
240+
goto put_folio;
245241

246242
folio_clear_referenced(folio);
247243
folio_test_clear_young(folio);
248-
if (!folio_isolate_lru(folio)) {
249-
folio_put(folio);
250-
continue;
251-
}
244+
if (!folio_isolate_lru(folio))
245+
goto put_folio;
252246
if (folio_test_unevictable(folio))
253247
folio_putback_lru(folio);
254248
else
255249
list_add(&folio->lru, &folio_list);
250+
put_folio:
256251
folio_put(folio);
257252
}
258253
applied = reclaim_pages(&folio_list);
@@ -271,16 +266,15 @@ static inline unsigned long damon_pa_mark_accessed_or_deactivate(
271266
if (!folio)
272267
continue;
273268

274-
if (damos_pa_filter_out(s, folio)) {
275-
folio_put(folio);
276-
continue;
277-
}
269+
if (damos_pa_filter_out(s, folio))
270+
goto put_folio;
278271

279272
if (mark_accessed)
280273
folio_mark_accessed(folio);
281274
else
282275
folio_deactivate(folio);
283276
applied += folio_nr_pages(folio);
277+
put_folio:
284278
folio_put(folio);
285279
}
286280
return applied * PAGE_SIZE;

mm/ksm.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,6 +2520,22 @@ static void __ksm_add_vma(struct vm_area_struct *vma)
25202520
vm_flags_set(vma, VM_MERGEABLE);
25212521
}
25222522

2523+
static int __ksm_del_vma(struct vm_area_struct *vma)
2524+
{
2525+
int err;
2526+
2527+
if (!(vma->vm_flags & VM_MERGEABLE))
2528+
return 0;
2529+
2530+
if (vma->anon_vma) {
2531+
err = unmerge_ksm_pages(vma, vma->vm_start, vma->vm_end);
2532+
if (err)
2533+
return err;
2534+
}
2535+
2536+
vm_flags_clear(vma, VM_MERGEABLE);
2537+
return 0;
2538+
}
25232539
/**
25242540
* ksm_add_vma - Mark vma as mergeable if compatible
25252541
*
@@ -2542,6 +2558,20 @@ static void ksm_add_vmas(struct mm_struct *mm)
25422558
__ksm_add_vma(vma);
25432559
}
25442560

2561+
static int ksm_del_vmas(struct mm_struct *mm)
2562+
{
2563+
struct vm_area_struct *vma;
2564+
int err;
2565+
2566+
VMA_ITERATOR(vmi, mm, 0);
2567+
for_each_vma(vmi, vma) {
2568+
err = __ksm_del_vma(vma);
2569+
if (err)
2570+
return err;
2571+
}
2572+
return 0;
2573+
}
2574+
25452575
/**
25462576
* ksm_enable_merge_any - Add mm to mm ksm list and enable merging on all
25472577
* compatible VMA's
@@ -2569,6 +2599,46 @@ int ksm_enable_merge_any(struct mm_struct *mm)
25692599
return 0;
25702600
}
25712601

2602+
/**
2603+
* ksm_disable_merge_any - Disable merging on all compatible VMA's of the mm,
2604+
* previously enabled via ksm_enable_merge_any().
2605+
*
2606+
* Disabling merging implies unmerging any merged pages, like setting
2607+
* MADV_UNMERGEABLE would. If unmerging fails, the whole operation fails and
2608+
* merging on all compatible VMA's remains enabled.
2609+
*
2610+
* @mm: Pointer to mm
2611+
*
2612+
* Returns 0 on success, otherwise error code
2613+
*/
2614+
int ksm_disable_merge_any(struct mm_struct *mm)
2615+
{
2616+
int err;
2617+
2618+
if (!test_bit(MMF_VM_MERGE_ANY, &mm->flags))
2619+
return 0;
2620+
2621+
err = ksm_del_vmas(mm);
2622+
if (err) {
2623+
ksm_add_vmas(mm);
2624+
return err;
2625+
}
2626+
2627+
clear_bit(MMF_VM_MERGE_ANY, &mm->flags);
2628+
return 0;
2629+
}
2630+
2631+
int ksm_disable(struct mm_struct *mm)
2632+
{
2633+
mmap_assert_write_locked(mm);
2634+
2635+
if (!test_bit(MMF_VM_MERGEABLE, &mm->flags))
2636+
return 0;
2637+
if (test_bit(MMF_VM_MERGE_ANY, &mm->flags))
2638+
return ksm_disable_merge_any(mm);
2639+
return ksm_del_vmas(mm);
2640+
}
2641+
25722642
int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
25732643
unsigned long end, int advice, unsigned long *vm_flags)
25742644
{

mm/page_alloc.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,15 @@ void __free_pages_core(struct page *page, unsigned int order)
15021502
* interleaving within a single pageblock. It is therefore sufficient to check
15031503
* the first and last page of a pageblock and avoid checking each individual
15041504
* page in a pageblock.
1505+
*
1506+
* Note: the function may return non-NULL struct page even for a page block
1507+
* which contains a memory hole (i.e. there is no physical memory for a subset
1508+
* of the pfn range). For example, if the pageblock order is MAX_ORDER, which
1509+
* will fall into 2 sub-sections, and the end pfn of the pageblock may be hole
1510+
* even though the start pfn is online and valid. This should be safe most of
1511+
* the time because struct pages are still initialized via init_unavailable_range()
1512+
* and pfn walkers shouldn't touch any physical memory range for which they do
1513+
* not recognize any specific metadata in struct pages.
15051514
*/
15061515
struct page *__pageblock_pfn_to_page(unsigned long start_pfn,
15071516
unsigned long end_pfn, struct zone *zone)

0 commit comments

Comments
 (0)