* [PATCH v2 0/4] mm: improve clear and copy user folio
@ 2024-06-18 9:12 Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 1/4] mm: memory: convert clear_huge_page() to folio_zero_user() Kefeng Wang
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Kefeng Wang @ 2024-06-18 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Matthew Wilcox (Oracle),
David Hildenbrand, linux-mm, Huang Ying, Kefeng Wang
The most are some folio conversions, another improvement is that move
address alignment into the caller as it is only needed if we don't know
which address will be accessed when clear/copy user folio.
v2:
- rename clear_large_folio to folio_zero_user and move alignment out,
per Matthew, but still use addr_hint name since it is for cache hint,
or maybe user_addr_hint ?
- improve copy_user_large_folio() and rename pages_per_huge_page
- add ACK
Kefeng Wang (4):
mm: memory: convert clear_huge_page() to folio_zero_user()
mm: memory: use folio in struct copy_subpage_arg
mm: memory: improve copy_user_large_folio()
mm: memory: rename pages_per_huge_page to nr_pages
fs/hugetlbfs/inode.c | 2 +-
include/linux/mm.h | 4 +--
mm/huge_memory.c | 4 +--
mm/hugetlb.c | 21 +++++-------
mm/memory.c | 81 +++++++++++++++++++++-----------------------
5 files changed, 51 insertions(+), 61 deletions(-)
--
2.27.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/4] mm: memory: convert clear_huge_page() to folio_zero_user()
2024-06-18 9:12 [PATCH v2 0/4] mm: improve clear and copy user folio Kefeng Wang
@ 2024-06-18 9:12 ` Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 2/4] mm: memory: use folio in struct copy_subpage_arg Kefeng Wang
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Kefeng Wang @ 2024-06-18 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Matthew Wilcox (Oracle),
David Hildenbrand, linux-mm, Huang Ying, Kefeng Wang
Replace clear_huge_page() with folio_zero_user(), and take a folio
instead of a page. Directly get number of pages by folio_nr_pages()
to remove pages_per_huge_page argument, furthermore, move the address
alignment from folio_zero_user() to the callers since the alignment
is only needed when we don't know which address will be accessed.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
fs/hugetlbfs/inode.c | 2 +-
include/linux/mm.h | 4 +---
mm/huge_memory.c | 4 ++--
mm/hugetlb.c | 3 +--
mm/memory.c | 34 ++++++++++++++++------------------
5 files changed, 21 insertions(+), 26 deletions(-)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 1107e5aa8343..ecad73a4f713 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -892,7 +892,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
error = PTR_ERR(folio);
goto out;
}
- clear_huge_page(&folio->page, addr, pages_per_huge_page(h));
+ folio_zero_user(folio, ALIGN_DOWN(addr, hpage_size));
__folio_mark_uptodate(folio);
error = hugetlb_add_to_page_cache(folio, mapping, index);
if (unlikely(error)) {
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 106bb0310352..ecbca6281a4e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4071,9 +4071,7 @@ enum mf_action_page_type {
};
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS)
-extern void clear_huge_page(struct page *page,
- unsigned long addr_hint,
- unsigned int pages_per_huge_page);
+void folio_zero_user(struct folio *folio, unsigned long addr_hint);
int copy_user_large_folio(struct folio *dst, struct folio *src,
unsigned long addr_hint,
struct vm_area_struct *vma);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index f409ea9fcc18..85b852861610 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -943,10 +943,10 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
goto release;
}
- clear_huge_page(page, vmf->address, HPAGE_PMD_NR);
+ folio_zero_user(folio, vmf->address);
/*
* The memory barrier inside __folio_mark_uptodate makes sure that
- * clear_huge_page writes become visible before the set_pmd_at()
+ * folio_zero_user writes become visible before the set_pmd_at()
* write.
*/
__folio_mark_uptodate(folio);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 3518321f6598..58d8703a1065 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -6296,8 +6296,7 @@ static vm_fault_t hugetlb_no_page(struct address_space *mapping,
ret = 0;
goto out;
}
- clear_huge_page(&folio->page, vmf->real_address,
- pages_per_huge_page(h));
+ folio_zero_user(folio, vmf->real_address);
__folio_mark_uptodate(folio);
new_folio = true;
diff --git a/mm/memory.c b/mm/memory.c
index 54d7d2acdf39..bc5d446d9174 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4477,7 +4477,7 @@ static struct folio *alloc_anon_folio(struct vm_fault *vmf)
goto next;
}
folio_throttle_swaprate(folio, gfp);
- clear_huge_page(&folio->page, vmf->address, 1 << order);
+ folio_zero_user(folio, vmf->address);
return folio;
}
next:
@@ -6420,41 +6420,39 @@ static inline int process_huge_page(
return 0;
}
-static void clear_gigantic_page(struct page *page,
- unsigned long addr,
+static void clear_gigantic_page(struct folio *folio, unsigned long addr,
unsigned int pages_per_huge_page)
{
int i;
- struct page *p;
might_sleep();
for (i = 0; i < pages_per_huge_page; i++) {
- p = nth_page(page, i);
cond_resched();
- clear_user_highpage(p, addr + i * PAGE_SIZE);
+ clear_user_highpage(folio_page(folio, i), addr + i * PAGE_SIZE);
}
}
static int clear_subpage(unsigned long addr, int idx, void *arg)
{
- struct page *page = arg;
+ struct folio *folio = arg;
- clear_user_highpage(nth_page(page, idx), addr);
+ clear_user_highpage(folio_page(folio, idx), addr);
return 0;
}
-void clear_huge_page(struct page *page,
- unsigned long addr_hint, unsigned int pages_per_huge_page)
+/**
+ * folio_zero_user - Zero a folio which will be mapped to userspace.
+ * @folio: The folio to zero.
+ * @addr_hint: The address will be accessed or the base address if uncelar.
+ */
+void folio_zero_user(struct folio *folio, unsigned long addr_hint)
{
- unsigned long addr = addr_hint &
- ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1);
+ unsigned int nr_pages = folio_nr_pages(folio);
- if (unlikely(pages_per_huge_page > MAX_ORDER_NR_PAGES)) {
- clear_gigantic_page(page, addr, pages_per_huge_page);
- return;
- }
-
- process_huge_page(addr_hint, pages_per_huge_page, clear_subpage, page);
+ if (unlikely(nr_pages > MAX_ORDER_NR_PAGES))
+ clear_gigantic_page(folio, addr_hint, nr_pages);
+ else
+ process_huge_page(addr_hint, nr_pages, clear_subpage, folio);
}
static int copy_user_gigantic_page(struct folio *dst, struct folio *src,
--
2.27.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/4] mm: memory: use folio in struct copy_subpage_arg
2024-06-18 9:12 [PATCH v2 0/4] mm: improve clear and copy user folio Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 1/4] mm: memory: convert clear_huge_page() to folio_zero_user() Kefeng Wang
@ 2024-06-18 9:12 ` Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 3/4] mm: memory: improve copy_user_large_folio() Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 4/4] mm: memory: rename pages_per_huge_page to nr_pages Kefeng Wang
3 siblings, 0 replies; 5+ messages in thread
From: Kefeng Wang @ 2024-06-18 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Matthew Wilcox (Oracle),
David Hildenbrand, linux-mm, Huang Ying, Kefeng Wang
Directly use folio in struct copy_subpage_arg.
Acked-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
mm/memory.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index bc5d446d9174..a48a790a2b5b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -6477,16 +6477,16 @@ static int copy_user_gigantic_page(struct folio *dst, struct folio *src,
}
struct copy_subpage_arg {
- struct page *dst;
- struct page *src;
+ struct folio *dst;
+ struct folio *src;
struct vm_area_struct *vma;
};
static int copy_subpage(unsigned long addr, int idx, void *arg)
{
struct copy_subpage_arg *copy_arg = arg;
- struct page *dst = nth_page(copy_arg->dst, idx);
- struct page *src = nth_page(copy_arg->src, idx);
+ struct page *dst = folio_page(copy_arg->dst, idx);
+ struct page *src = folio_page(copy_arg->src, idx);
if (copy_mc_user_highpage(dst, src, addr, copy_arg->vma))
return -EHWPOISON;
@@ -6500,8 +6500,8 @@ int copy_user_large_folio(struct folio *dst, struct folio *src,
unsigned long addr = addr_hint &
~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1);
struct copy_subpage_arg arg = {
- .dst = &dst->page,
- .src = &src->page,
+ .dst = dst,
+ .src = src,
.vma = vma,
};
--
2.27.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 3/4] mm: memory: improve copy_user_large_folio()
2024-06-18 9:12 [PATCH v2 0/4] mm: improve clear and copy user folio Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 1/4] mm: memory: convert clear_huge_page() to folio_zero_user() Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 2/4] mm: memory: use folio in struct copy_subpage_arg Kefeng Wang
@ 2024-06-18 9:12 ` Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 4/4] mm: memory: rename pages_per_huge_page to nr_pages Kefeng Wang
3 siblings, 0 replies; 5+ messages in thread
From: Kefeng Wang @ 2024-06-18 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Matthew Wilcox (Oracle),
David Hildenbrand, linux-mm, Huang Ying, Kefeng Wang
Use nr_pages instead of pages_per_huge_page and move the address
alignment from copy_user_large_folio() into the callers since it
is only needed when we don't know which address will be accessed.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
mm/hugetlb.c | 18 ++++++++----------
mm/memory.c | 11 ++++-------
2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 58d8703a1065..a41afeeb2188 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5488,9 +5488,8 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
ret = PTR_ERR(new_folio);
break;
}
- ret = copy_user_large_folio(new_folio,
- pte_folio,
- addr, dst_vma);
+ ret = copy_user_large_folio(new_folio, pte_folio,
+ ALIGN_DOWN(addr, sz), dst_vma);
folio_put(pte_folio);
if (ret) {
folio_put(new_folio);
@@ -6680,7 +6679,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
struct hstate *h = hstate_vma(dst_vma);
struct address_space *mapping = dst_vma->vm_file->f_mapping;
pgoff_t idx = vma_hugecache_offset(h, dst_vma, dst_addr);
- unsigned long size;
+ unsigned long size = huge_page_size(h);
int vm_shared = dst_vma->vm_flags & VM_SHARED;
pte_t _dst_pte;
spinlock_t *ptl;
@@ -6699,8 +6698,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
}
_dst_pte = make_pte_marker(PTE_MARKER_POISONED);
- set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte,
- huge_page_size(h));
+ set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, size);
/* No need to invalidate - it was non-present before */
update_mmu_cache(dst_vma, dst_addr, dst_pte);
@@ -6774,7 +6772,8 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
*foliop = NULL;
goto out;
}
- ret = copy_user_large_folio(folio, *foliop, dst_addr, dst_vma);
+ ret = copy_user_large_folio(folio, *foliop,
+ ALIGN_DOWN(dst_addr, size), dst_vma);
folio_put(*foliop);
*foliop = NULL;
if (ret) {
@@ -6801,9 +6800,8 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
/* Add shared, newly allocated pages to the page cache. */
if (vm_shared && !is_continue) {
- size = i_size_read(mapping->host) >> huge_page_shift(h);
ret = -EFAULT;
- if (idx >= size)
+ if (idx >= (i_size_read(mapping->host) >> huge_page_shift(h)))
goto out_release_nounlock;
/*
@@ -6860,7 +6858,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
if (wp_enabled)
_dst_pte = huge_pte_mkuffd_wp(_dst_pte);
- set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, huge_page_size(h));
+ set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte, size);
hugetlb_count_add(pages_per_huge_page(h), dst_mm);
diff --git a/mm/memory.c b/mm/memory.c
index a48a790a2b5b..12115e45dc24 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -6496,20 +6496,17 @@ static int copy_subpage(unsigned long addr, int idx, void *arg)
int copy_user_large_folio(struct folio *dst, struct folio *src,
unsigned long addr_hint, struct vm_area_struct *vma)
{
- unsigned int pages_per_huge_page = folio_nr_pages(dst);
- unsigned long addr = addr_hint &
- ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1);
+ unsigned int nr_pages = folio_nr_pages(dst);
struct copy_subpage_arg arg = {
.dst = dst,
.src = src,
.vma = vma,
};
- if (unlikely(pages_per_huge_page > MAX_ORDER_NR_PAGES))
- return copy_user_gigantic_page(dst, src, addr, vma,
- pages_per_huge_page);
+ if (unlikely(nr_pages > MAX_ORDER_NR_PAGES))
+ return copy_user_gigantic_page(dst, src, addr_hint, vma, nr_pages);
- return process_huge_page(addr_hint, pages_per_huge_page, copy_subpage, &arg);
+ return process_huge_page(addr_hint, nr_pages, copy_subpage, &arg);
}
long copy_folio_from_user(struct folio *dst_folio,
--
2.27.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 4/4] mm: memory: rename pages_per_huge_page to nr_pages
2024-06-18 9:12 [PATCH v2 0/4] mm: improve clear and copy user folio Kefeng Wang
` (2 preceding siblings ...)
2024-06-18 9:12 ` [PATCH v2 3/4] mm: memory: improve copy_user_large_folio() Kefeng Wang
@ 2024-06-18 9:12 ` Kefeng Wang
3 siblings, 0 replies; 5+ messages in thread
From: Kefeng Wang @ 2024-06-18 9:12 UTC (permalink / raw)
To: Andrew Morton
Cc: Muchun Song, Matthew Wilcox (Oracle),
David Hildenbrand, linux-mm, Huang Ying, Kefeng Wang
Since the callers are converted to use nr_pages naming, use it inside too.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
mm/memory.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 12115e45dc24..d48879e317b3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -6366,23 +6366,23 @@ EXPORT_SYMBOL(__might_fault);
* cache lines hot.
*/
static inline int process_huge_page(
- unsigned long addr_hint, unsigned int pages_per_huge_page,
+ unsigned long addr_hint, unsigned int nr_pages,
int (*process_subpage)(unsigned long addr, int idx, void *arg),
void *arg)
{
int i, n, base, l, ret;
unsigned long addr = addr_hint &
- ~(((unsigned long)pages_per_huge_page << PAGE_SHIFT) - 1);
+ ~(((unsigned long)nr_pages << PAGE_SHIFT) - 1);
/* Process target subpage last to keep its cache lines hot */
might_sleep();
n = (addr_hint - addr) / PAGE_SIZE;
- if (2 * n <= pages_per_huge_page) {
+ if (2 * n <= nr_pages) {
/* If target subpage in first half of huge page */
base = 0;
l = n;
/* Process subpages at the end of huge page */
- for (i = pages_per_huge_page - 1; i >= 2 * n; i--) {
+ for (i = nr_pages - 1; i >= 2 * n; i--) {
cond_resched();
ret = process_subpage(addr + i * PAGE_SIZE, i, arg);
if (ret)
@@ -6390,8 +6390,8 @@ static inline int process_huge_page(
}
} else {
/* If target subpage in second half of huge page */
- base = pages_per_huge_page - 2 * (pages_per_huge_page - n);
- l = pages_per_huge_page - n;
+ base = nr_pages - 2 * (nr_pages - n);
+ l = nr_pages - n;
/* Process subpages at the begin of huge page */
for (i = 0; i < base; i++) {
cond_resched();
@@ -6421,12 +6421,12 @@ static inline int process_huge_page(
}
static void clear_gigantic_page(struct folio *folio, unsigned long addr,
- unsigned int pages_per_huge_page)
+ unsigned int nr_pages)
{
int i;
might_sleep();
- for (i = 0; i < pages_per_huge_page; i++) {
+ for (i = 0; i < nr_pages; i++) {
cond_resched();
clear_user_highpage(folio_page(folio, i), addr + i * PAGE_SIZE);
}
@@ -6456,15 +6456,15 @@ void folio_zero_user(struct folio *folio, unsigned long addr_hint)
}
static int copy_user_gigantic_page(struct folio *dst, struct folio *src,
- unsigned long addr,
- struct vm_area_struct *vma,
- unsigned int pages_per_huge_page)
+ unsigned long addr,
+ struct vm_area_struct *vma,
+ unsigned int nr_pages)
{
int i;
struct page *dst_page;
struct page *src_page;
- for (i = 0; i < pages_per_huge_page; i++) {
+ for (i = 0; i < nr_pages; i++) {
dst_page = folio_page(dst, i);
src_page = folio_page(src, i);
--
2.27.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-06-18 9:13 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-18 9:12 [PATCH v2 0/4] mm: improve clear and copy user folio Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 1/4] mm: memory: convert clear_huge_page() to folio_zero_user() Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 2/4] mm: memory: use folio in struct copy_subpage_arg Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 3/4] mm: memory: improve copy_user_large_folio() Kefeng Wang
2024-06-18 9:12 ` [PATCH v2 4/4] mm: memory: rename pages_per_huge_page to nr_pages Kefeng Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox