linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Joel Fernandes <joel@joelfernandes.org>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
	 Andrew Morton <akpm@linux-foundation.org>,
	Linux-MM <linux-mm@kvack.org>,
	 Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Naresh Kamboju <naresh.kamboju@linaro.org>,
	 William Kucharski <william.kucharski@oracle.com>
Subject: Re: [PATCHv2] mm: Fix warning in move_normal_pmd()
Date: Wed, 15 Jul 2020 14:43:00 -0700	[thread overview]
Message-ID: <CAHk-=wg+iVwK7MDXB+BPbhTmP-1eBa-y4vxRNr_G8ETnzv5pZg@mail.gmail.com> (raw)
In-Reply-To: <CAHk-=wg-_Oof43pKUHMk4ySdLwpYi7+shFg+aeV18UP2Akiv8g@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 520 bytes --]

On Wed, Jul 15, 2020 at 2:31 PM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> Naresh - don't test that version. The bugs Joel found just make the
> math wrong, so it won't work.

Here's a new version with the thing that Joel and Kirill both noticed
hopefully fixed.

But I probably screwed it up again. I guess I should test it, but I
don't have any really relevant environment (the plain mremap() case
should have shown the obvious bugs, though, so that's just an excuse
for my laziness)

            Linus

[-- Attachment #2: patch --]
[-- Type: application/octet-stream, Size: 2634 bytes --]

diff --git a/mm/mremap.c b/mm/mremap.c
index 5dd572d57ca9..614b4fffed1d 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -235,6 +235,71 @@ static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr,
 
 	return true;
 }
+
+#define ADDR_BEFORE_PREV(addr, vma) \
+	((vma)->vm_prev && (addr) < (vma)->vm_prev->vm_end)
+
+static inline void try_to_align_start(unsigned long *len,
+	struct vm_area_struct *old, unsigned long *old_addr,
+	struct vm_area_struct *new, unsigned long *new_addr)
+{
+	if (ADDR_BEFORE_PREV(*old_addr & PMD_MASK, old))
+		return;
+
+	if (ADDR_BEFORE_PREV(*new_addr & PMD_MASK, new))
+		return;
+
+	/* Bingo! */
+	*len += *new_addr & ~PMD_MASK;
+	*old_addr &= PMD_MASK;
+	*new_addr &= PMD_MASK;
+}
+
+/*
+ * When aligning the end, avoid ALIGN() (which can overflow
+ * if the user space is the full address space, and overshoot
+ * the vm_start of the next vma).
+ *
+ * Align the upper limit down instead, and check that it's not
+ * in the same PMD as the end.
+ */
+#define ADDR_AFTER_NEXT(addr, vma) \
+	((vma)->vm_next && (addr) > (PMD_MASK & (vma)->vm_next->vm_start))
+
+static inline void try_to_align_end(unsigned long *len,
+	struct vm_area_struct *old, unsigned long *old_addr,
+	struct vm_area_struct *new, unsigned long *new_addr)
+{
+	if (ADDR_AFTER_NEXT(*old_addr + *len, old))
+		return;
+
+	if (ADDR_AFTER_NEXT(*new_addr + *len, new))
+		return;
+
+	/* Mutual alignment means this is same for new/old addr */
+	*len = ALIGN(*new_addr + *len, PMD_SIZE) - *new_addr;
+}
+
+/*
+ * The PMD move case is much more efficient, so if we have the
+ * mutually aligned case, try to see if we can extend the
+ * beginning and end to be aligned too.
+ *
+ * The pointer dereferences look bad, but with inlining, the
+ * compiler will sort it out.
+ */
+static inline void try_to_align_range(unsigned long *len,
+	struct vm_area_struct *old, unsigned long *old_addr,
+	struct vm_area_struct *new, unsigned long *new_addr)
+{
+	if ((*old_addr ^ *new_addr) & ~PMD_MASK)
+		return;
+
+	try_to_align_start(len, old, old_addr, new, new_addr);
+	try_to_align_end(len, old, old_addr, new, new_addr);
+}
+#else
+#define try_to_align_range(len,old,olda,new,newa) do { } while(0);
 #endif
 
 unsigned long move_page_tables(struct vm_area_struct *vma,
@@ -253,6 +318,8 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
 				old_addr, old_end);
 	mmu_notifier_invalidate_range_start(&range);
 
+	try_to_align_range(&len, vma, &old_addr, new_vma, &new_addr);
+
 	for (; old_addr < old_end; old_addr += extent, new_addr += extent) {
 		cond_resched();
 		next = (old_addr + PMD_SIZE) & PMD_MASK;

  reply	other threads:[~2020-07-15 21:43 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-15 13:50 Kirill A. Shutemov
2020-07-15 18:36 ` Linus Torvalds
2020-07-15 20:54   ` Joel Fernandes
2020-07-15 21:13     ` Kirill A. Shutemov
2020-07-15 21:31     ` Linus Torvalds
2020-07-15 21:43       ` Linus Torvalds [this message]
2020-07-15 22:22         ` Kirill A. Shutemov
2020-07-15 22:36           ` Linus Torvalds
2020-07-15 22:57           ` Linus Torvalds
2020-07-15 23:04             ` Linus Torvalds
2020-07-15 23:18               ` Linus Torvalds
2020-07-16  6:37                 ` Naresh Kamboju
2020-07-16  7:23                   ` Naresh Kamboju
2020-07-16  8:46                     ` Kirill A. Shutemov
2020-07-16  8:32                 ` Naresh Kamboju
2020-07-16 13:16                 ` Kirill A. Shutemov
2020-07-16 17:54                   ` Linus Torvalds
2020-07-16 18:47                     ` Joel Fernandes
2020-07-15 20:55   ` Kirill A. Shutemov
2020-07-15 21:35     ` Linus Torvalds
2020-07-15 21:51       ` Linus Torvalds

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAHk-=wg+iVwK7MDXB+BPbhTmP-1eBa-y4vxRNr_G8ETnzv5pZg@mail.gmail.com' \
    --to=torvalds@linux-foundation.org \
    --cc=akpm@linux-foundation.org \
    --cc=joel@joelfernandes.org \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=naresh.kamboju@linaro.org \
    --cc=william.kucharski@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox