In preparation for later changes, refactor out a new function called
try_to_merge_with_zero_page(), which tries to merge with zero page.
Signed-off-by: Chengming Zhou <chengming.zhou@linux.dev>
---
mm/ksm.c | 67 +++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 37 insertions(+), 30 deletions(-)
diff --git a/mm/ksm.c b/mm/ksm.c
index 4dc707d175fa..cbd4ba7ea974 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1531,6 +1531,41 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
return err;
}
+/* This function returns 0 if the pages were merged, -EFAULT otherwise. */
+static int try_to_merge_with_zero_page(struct ksm_rmap_item *rmap_item,
+ struct page *page)
+{
+ struct mm_struct *mm = rmap_item->mm;
+ int err = -EFAULT;
+
+ /*
+ * Same checksum as an empty page. We attempt to merge it with the
+ * appropriate zero page if the user enabled this via sysfs.
+ */
+ if (ksm_use_zero_pages && (rmap_item->oldchecksum == zero_checksum)) {
+ struct vm_area_struct *vma;
+
+ mmap_read_lock(mm);
+ vma = find_mergeable_vma(mm, rmap_item->address);
+ if (vma) {
+ err = try_to_merge_one_page(vma, page,
+ ZERO_PAGE(rmap_item->address));
+ trace_ksm_merge_one_page(
+ page_to_pfn(ZERO_PAGE(rmap_item->address)),
+ rmap_item, mm, err);
+ } else {
+ /*
+ * If the vma is out of date, we do not need to
+ * continue.
+ */
+ err = 0;
+ }
+ mmap_read_unlock(mm);
+ }
+
+ return err;
+}
+
/*
* try_to_merge_with_ksm_page - like try_to_merge_two_pages,
* but no new kernel page is allocated: kpage must already be a ksm page.
@@ -2305,7 +2340,6 @@ static void stable_tree_append(struct ksm_rmap_item *rmap_item,
*/
static noinline void cmp_and_merge_page(struct page *page, struct ksm_rmap_item *rmap_item)
{
- struct mm_struct *mm = rmap_item->mm;
struct ksm_rmap_item *tree_rmap_item;
struct page *tree_page = NULL;
struct ksm_stable_node *stable_node;
@@ -2374,36 +2408,9 @@ static noinline void cmp_and_merge_page(struct page *page, struct ksm_rmap_item
return;
}
- /*
- * Same checksum as an empty page. We attempt to merge it with the
- * appropriate zero page if the user enabled this via sysfs.
- */
- if (ksm_use_zero_pages && (checksum == zero_checksum)) {
- struct vm_area_struct *vma;
+ if (!try_to_merge_with_zero_page(rmap_item, page))
+ return;
- mmap_read_lock(mm);
- vma = find_mergeable_vma(mm, rmap_item->address);
- if (vma) {
- err = try_to_merge_one_page(vma, page,
- ZERO_PAGE(rmap_item->address));
- trace_ksm_merge_one_page(
- page_to_pfn(ZERO_PAGE(rmap_item->address)),
- rmap_item, mm, err);
- } else {
- /*
- * If the vma is out of date, we do not need to
- * continue.
- */
- err = 0;
- }
- mmap_read_unlock(mm);
- /*
- * In case of failure, the page was not really empty, so we
- * need to continue. Otherwise we're done.
- */
- if (!err)
- return;
- }
tree_rmap_item =
unstable_tree_search_insert(rmap_item, page, &tree_page);
if (tree_rmap_item) {
--
2.45.1
On 24.05.24 10:56, Chengming Zhou wrote: > In preparation for later changes, refactor out a new function called > try_to_merge_with_zero_page(), which tries to merge with zero page. > > Signed-off-by: Chengming Zhou <chengming.zhou@linux.dev> > --- > mm/ksm.c | 67 +++++++++++++++++++++++++++++++++++----------------------------- > 1 file changed, 37 insertions(+), 30 deletions(-) > > diff --git a/mm/ksm.c b/mm/ksm.c > index 4dc707d175fa..cbd4ba7ea974 100644 > --- a/mm/ksm.c > +++ b/mm/ksm.c > @@ -1531,6 +1531,41 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, > return err; > } > > +/* This function returns 0 if the pages were merged, -EFAULT otherwise. */ No it doesn't. Check the "err = 0" case. -- Cheers, David / dhildenb
On 2024/5/24 23:12, David Hildenbrand wrote: > On 24.05.24 10:56, Chengming Zhou wrote: >> In preparation for later changes, refactor out a new function called >> try_to_merge_with_zero_page(), which tries to merge with zero page. >> >> Signed-off-by: Chengming Zhou <chengming.zhou@linux.dev> >> --- >> mm/ksm.c | 67 +++++++++++++++++++++++++++++++++++----------------------------- >> 1 file changed, 37 insertions(+), 30 deletions(-) >> >> diff --git a/mm/ksm.c b/mm/ksm.c >> index 4dc707d175fa..cbd4ba7ea974 100644 >> --- a/mm/ksm.c >> +++ b/mm/ksm.c >> @@ -1531,6 +1531,41 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, >> return err; >> } >> +/* This function returns 0 if the pages were merged, -EFAULT otherwise. */ > > No it doesn't. Check the "err = 0" case. > Right, how about this: This function returns 0 if the page were merged or the vma is out of date, which means we don't need to continue, -EFAULT otherwise.
Am 27.05.24 um 06:36 schrieb Chengming Zhou: > On 2024/5/24 23:12, David Hildenbrand wrote: >> On 24.05.24 10:56, Chengming Zhou wrote: >>> In preparation for later changes, refactor out a new function called >>> try_to_merge_with_zero_page(), which tries to merge with zero page. >>> >>> Signed-off-by: Chengming Zhou <chengming.zhou@linux.dev> >>> --- >>> mm/ksm.c | 67 +++++++++++++++++++++++++++++++++++----------------------------- >>> 1 file changed, 37 insertions(+), 30 deletions(-) >>> >>> diff --git a/mm/ksm.c b/mm/ksm.c >>> index 4dc707d175fa..cbd4ba7ea974 100644 >>> --- a/mm/ksm.c >>> +++ b/mm/ksm.c >>> @@ -1531,6 +1531,41 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, >>> return err; >>> } >>> +/* This function returns 0 if the pages were merged, -EFAULT otherwise. */ >> >> No it doesn't. Check the "err = 0" case. >> > > Right, how about this: This function returns 0 if the page were merged or the vma > is out of date, which means we don't need to continue, -EFAULT otherwise. Maybe slightly adjusted: This function returns 0 if the pages were merged or if they are no longer merging candidates (e.g., VMA stale), -EFAULT otherwise. -- Thanks, David / dhildenb
On 2024/5/27 15:18, David Hildenbrand wrote: > Am 27.05.24 um 06:36 schrieb Chengming Zhou: >> On 2024/5/24 23:12, David Hildenbrand wrote: >>> On 24.05.24 10:56, Chengming Zhou wrote: >>>> In preparation for later changes, refactor out a new function called >>>> try_to_merge_with_zero_page(), which tries to merge with zero page. >>>> >>>> Signed-off-by: Chengming Zhou <chengming.zhou@linux.dev> >>>> --- >>>> mm/ksm.c | 67 +++++++++++++++++++++++++++++++++++----------------------------- >>>> 1 file changed, 37 insertions(+), 30 deletions(-) >>>> >>>> diff --git a/mm/ksm.c b/mm/ksm.c >>>> index 4dc707d175fa..cbd4ba7ea974 100644 >>>> --- a/mm/ksm.c >>>> +++ b/mm/ksm.c >>>> @@ -1531,6 +1531,41 @@ static int try_to_merge_one_page(struct vm_area_struct *vma, >>>> return err; >>>> } >>>> +/* This function returns 0 if the pages were merged, -EFAULT otherwise. */ >>> >>> No it doesn't. Check the "err = 0" case. >>> >> >> Right, how about this: This function returns 0 if the page were merged or the vma >> is out of date, which means we don't need to continue, -EFAULT otherwise. > > Maybe slightly adjusted: > > This function returns 0 if the pages were merged or if they are no longer merging candidates (e.g., VMA stale), -EFAULT otherwise. > Great, will change to this. Thanks!
© 2016 - 2026 Red Hat, Inc.