From patchwork Mon Oct 9 20:53:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Stoakes X-Patchwork-Id: 13414423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65B0DCD6139 for ; Mon, 9 Oct 2023 20:53:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378037AbjJIUxl (ORCPT ); Mon, 9 Oct 2023 16:53:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57940 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1377082AbjJIUxj (ORCPT ); Mon, 9 Oct 2023 16:53:39 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 52E80A6; Mon, 9 Oct 2023 13:53:36 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-3226cc3e324so4909135f8f.3; Mon, 09 Oct 2023 13:53:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696884815; x=1697489615; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jochmgf2oxyHl1Fdsf6/Z0vhz675AmN7EMJ3Y7JXYH0=; b=BlWJ928czCmxUXHE9yDaFekmYQwrwx2M2dTJanSHnTnpcm46T43q+2BbSriIBCggCI omrl1Hfstn+EySkzfXES7l05BZrUMEGxPu8Ctszr2DakSA0ODmPzjdFBXTqAawUwHmj0 4ORfBid86/rdQzFAwUQ90zyDRafz5K+7ZXTPbB90eSciLoYvtUbwOyIqLea37vvXaIRV u4Yop//TPjkvD+Y+86Nk4OW2s8f1IRQ9IZE65DweR1lLxBE5qsI+2pmQkjcqsY2ThOBx 7HKphHQvdAo3ajbOjGs2/Mi81owBKUhZqXPYT+fFTG1yYOIVdbmAifiaWe2+DSEeKRuk bTZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696884815; x=1697489615; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jochmgf2oxyHl1Fdsf6/Z0vhz675AmN7EMJ3Y7JXYH0=; b=hUBdnKbt1nxxm0tYc9wLT6/QT3L4uAetdR/b0h9wAZpIhQ5S8g+GnSGLldFnGReWwd fxl3m9vERc6Gx1ZYIxorP0nEpuKJ8u9xaF7uDND+Jzsc64TiSo+bCmoc8IWkQsWE/lQQ Lds3dU+PzyoGUepjAD1mFDMOqSOOJicqIDnvdKzmVfEhrYw4HetlfK6oF9el+oor7DOZ z2nKpaG8ITgBX0frc2PaZVprazC8cyPpeqFcytVJ9sS1u2GZN6BvGdpvL8E/zB/bXeTQ cn5vqGrkJ0IWSObPLGOg5NPmqQX8l61HL2R8TVmTHH/eJ5ywUNXJ1DangG23B4EKONOV aTgg== X-Gm-Message-State: AOJu0YzsRxZC4gVm4uXNZtcea7uKnBBXfJVx7kK5yXHt1NosP11fPoe5 seK08Ze2CG0Fs6xrhsJJu/8= X-Google-Smtp-Source: AGHT+IEili6yjcpf1CIpTHpX1KIvbP9i7YisloKuaIxOeqWIbartUF3HE3nQKw8VeOEZ+cxXGxy9ng== X-Received: by 2002:a5d:4dcc:0:b0:321:62b0:7ad8 with SMTP id f12-20020a5d4dcc000000b0032162b07ad8mr14148854wru.16.1696884814438; Mon, 09 Oct 2023 13:53:34 -0700 (PDT) Received: from lucifer.home ([2a00:23c5:dc8c:8701:1663:9a35:5a7b:1d76]) by smtp.googlemail.com with ESMTPSA id l2-20020a5d4802000000b0031fe0576460sm10578130wrq.11.2023.10.09.13.53.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 13:53:33 -0700 (PDT) From: Lorenzo Stoakes To: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrew Morton , Alexander Viro , Christian Brauner Cc: "=Liam R . Howlett" , Vlastimil Babka , linux-fsdevel@vger.kernel.org, Lorenzo Stoakes Subject: [PATCH v2 1/5] mm: move vma_policy() and anon_vma_name() decls to mm_types.h Date: Mon, 9 Oct 2023 21:53:16 +0100 Message-ID: <4f1063f9c0e05ada89458083476e03434498e81e.1696884493.git.lstoakes@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The vma_policy() define is a helper specifically for a VMA field so it makes sense to host it in the memory management types header. The anon_vma_name(), anon_vma_name_alloc() and anon_vma_name_free() functions are a little out of place in mm_inline.h as they define external functions, and so it makes sense to locate them in mm_types.h. The purpose of these relocations is to make it possible to abstract static inline wrappers which invoke both of these helpers. Signed-off-by: Lorenzo Stoakes Reviewed-by: Vlastimil Babka --- include/linux/mempolicy.h | 4 ---- include/linux/mm_inline.h | 20 +------------------- include/linux/mm_types.h | 27 +++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 3c208d4f0ee9..2801d5b0a4e9 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -89,8 +89,6 @@ static inline struct mempolicy *mpol_dup(struct mempolicy *pol) return pol; } -#define vma_policy(vma) ((vma)->vm_policy) - static inline void mpol_get(struct mempolicy *pol) { if (pol) @@ -222,8 +220,6 @@ static inline struct mempolicy *get_vma_policy(struct vm_area_struct *vma, return NULL; } -#define vma_policy(vma) NULL - static inline int vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst) { diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 8148b30a9df1..9ae7def16cb2 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -352,15 +353,6 @@ void lruvec_del_folio(struct lruvec *lruvec, struct folio *folio) } #ifdef CONFIG_ANON_VMA_NAME -/* - * mmap_lock should be read-locked when calling anon_vma_name(). Caller should - * either keep holding the lock while using the returned pointer or it should - * raise anon_vma_name refcount before releasing the lock. - */ -extern struct anon_vma_name *anon_vma_name(struct vm_area_struct *vma); -extern struct anon_vma_name *anon_vma_name_alloc(const char *name); -extern void anon_vma_name_free(struct kref *kref); - /* mmap_lock should be read-locked */ static inline void anon_vma_name_get(struct anon_vma_name *anon_name) { @@ -415,16 +407,6 @@ static inline bool anon_vma_name_eq(struct anon_vma_name *anon_name1, } #else /* CONFIG_ANON_VMA_NAME */ -static inline struct anon_vma_name *anon_vma_name(struct vm_area_struct *vma) -{ - return NULL; -} - -static inline struct anon_vma_name *anon_vma_name_alloc(const char *name) -{ - return NULL; -} - static inline void anon_vma_name_get(struct anon_vma_name *anon_name) {} static inline void anon_vma_name_put(struct anon_vma_name *anon_name) {} static inline void dup_anon_vma_name(struct vm_area_struct *orig_vma, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 36c5b43999e6..21eb56145f57 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -546,6 +546,27 @@ struct anon_vma_name { char name[]; }; +#ifdef CONFIG_ANON_VMA_NAME +/* + * mmap_lock should be read-locked when calling anon_vma_name(). Caller should + * either keep holding the lock while using the returned pointer or it should + * raise anon_vma_name refcount before releasing the lock. + */ +struct anon_vma_name *anon_vma_name(struct vm_area_struct *vma); +struct anon_vma_name *anon_vma_name_alloc(const char *name); +void anon_vma_name_free(struct kref *kref); +#else /* CONFIG_ANON_VMA_NAME */ +static inline struct anon_vma_name *anon_vma_name(struct vm_area_struct *vma) +{ + return NULL; +} + +static inline struct anon_vma_name *anon_vma_name_alloc(const char *name) +{ + return NULL; +} +#endif + struct vma_lock { struct rw_semaphore lock; }; @@ -662,6 +683,12 @@ struct vm_area_struct { struct vm_userfaultfd_ctx vm_userfaultfd_ctx; } __randomize_layout; +#ifdef CONFIG_NUMA +#define vma_policy(vma) ((vma)->vm_policy) +#else +#define vma_policy(vma) NULL +#endif + #ifdef CONFIG_SCHED_MM_CID struct mm_cid { u64 time; From patchwork Mon Oct 9 20:53:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Stoakes X-Patchwork-Id: 13414426 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEC14CD6138 for ; Mon, 9 Oct 2023 20:54:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378202AbjJIUyH (ORCPT ); Mon, 9 Oct 2023 16:54:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378141AbjJIUxw (ORCPT ); Mon, 9 Oct 2023 16:53:52 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A6925BA; Mon, 9 Oct 2023 13:53:37 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-327be5fe4beso4567157f8f.3; Mon, 09 Oct 2023 13:53:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696884816; x=1697489616; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VKLx1ja8HeC2i05aZCboTLTuiLTHyhLExxAZQjBx8ig=; b=Rp/EY+YdAxDEyoR5gc5tjT9s8gCvmm8ZYkM/uP9eCcXVdabjGgGpEJxyoJKAskuDMb cnVwf3zQ7xLkmg31pUY2ljiTN1Po6RST7Co5FMvDidde8qq5CBLEEBQy76p0vvAwvFKV 8pxDv8sPqP059OpmPH0M3oIVBBad8gQa1Tp8JiJnqq4GiKl3ZBqcnZe15wbhQUQRqSaA g+piYWuZg6mEQ82cqQpf68VvoIyh128uLHzzv9S6+BPOvFxuMAAW0QQuZrQMe08j3/vN co9d/VtGLWwauT1bFi5zacEco8uWtEortPROphTE8c4QJgzhWGLwaZMe1sJBfGt43blq nPfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696884816; x=1697489616; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VKLx1ja8HeC2i05aZCboTLTuiLTHyhLExxAZQjBx8ig=; b=EIUqi1rlyeKYb6iN3qojftfF4gdonX2AoPuXr7DS50OPTBdodKS2W3BeI8e61OS98e SmYZA1+1ev1Njdonyc54XBouerhlbNCqPR99CzrEmouJ1Hkwv8QSfUEOdOpn9WHruZT/ KavfhBm0z79AIKNk6CejFYxBXjPYWZXg3T6K39b+BGfXhtd/SXmCXJvlUyIBXUZUi8PB c8eVQD26ZH+wSaKQ65rjl5B8xGo/m6czxDazURdhimrCZJEZXsKjCXOxv1YVHhKYMM1A 3PZ/bG3qjnENvWY9fo4hSw9M3Wsjd8Lz/NEl8PQl0FBle/S9btK5wlrAY2KtBDVqvEV7 96wQ== X-Gm-Message-State: AOJu0YyIgrWSMoWIOAPKCNy1LccL8kBX95reNpVulnJfL4qy/uSssF48 tOMxsO5m73x5uc/5QpHYec0D/oFbUew= X-Google-Smtp-Source: AGHT+IE9EsWvW05b+ffVnXE+d0/62Zwj6srI+4rcsUf3IhmIEVtijSpGOd4JlWGDSz6OraG+tmIFYA== X-Received: by 2002:adf:f74f:0:b0:319:68ba:7c8e with SMTP id z15-20020adff74f000000b0031968ba7c8emr14458485wrp.38.1696884815913; Mon, 09 Oct 2023 13:53:35 -0700 (PDT) Received: from lucifer.home ([2a00:23c5:dc8c:8701:1663:9a35:5a7b:1d76]) by smtp.googlemail.com with ESMTPSA id l2-20020a5d4802000000b0031fe0576460sm10578130wrq.11.2023.10.09.13.53.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 13:53:34 -0700 (PDT) From: Lorenzo Stoakes To: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrew Morton , Alexander Viro , Christian Brauner Cc: "=Liam R . Howlett" , Vlastimil Babka , linux-fsdevel@vger.kernel.org, Lorenzo Stoakes Subject: [PATCH v2 2/5] mm: abstract the vma_merge()/split_vma() pattern for mprotect() et al. Date: Mon, 9 Oct 2023 21:53:17 +0100 Message-ID: X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org mprotect() and other functions which change VMA parameters over a range each employ a pattern of:- 1. Attempt to merge the range with adjacent VMAs. 2. If this fails, and the range spans a subset of the VMA, split it accordingly. This is open-coded and duplicated in each case. Also in each case most of the parameters passed to vma_merge() remain the same. Create a new function, vma_modify(), which abstracts this operation, accepting only those parameters which can be changed. To avoid the mess of invoking each function call with unnecessary parameters, create inline wrapper functions for each of the modify operations, parameterised only by what is required to perform the action. Note that the userfaultfd_release() case works even though it does not split VMAs - since start is set to vma->vm_start and end is set to vma->vm_end, the split logic does not trigger. In addition, since we calculate pgoff to be equal to vma->vm_pgoff + (start - vma->vm_start) >> PAGE_SHIFT, and start - vma->vm_start will be 0 in this instance, this invocation will remain unchanged. Signed-off-by: Lorenzo Stoakes Reviewed-by: Vlastimil Babka --- fs/userfaultfd.c | 69 +++++++++++++++------------------------------- include/linux/mm.h | 60 ++++++++++++++++++++++++++++++++++++++++ mm/madvise.c | 32 ++++++--------------- mm/mempolicy.c | 22 +++------------ mm/mlock.c | 27 +++++------------- mm/mmap.c | 45 ++++++++++++++++++++++++++++++ mm/mprotect.c | 35 +++++++---------------- 7 files changed, 157 insertions(+), 133 deletions(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index a7c6ef764e63..ba44a67a0a34 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -927,11 +927,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file) continue; } new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS; - prev = vma_merge(&vmi, mm, prev, vma->vm_start, vma->vm_end, - new_flags, vma->anon_vma, - vma->vm_file, vma->vm_pgoff, - vma_policy(vma), - NULL_VM_UFFD_CTX, anon_vma_name(vma)); + prev = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start, + vma->vm_end, new_flags, + NULL_VM_UFFD_CTX); + if (prev) { vma = prev; } else { @@ -1331,7 +1330,6 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, unsigned long start, end, vma_end; struct vma_iterator vmi; bool wp_async = userfaultfd_wp_async_ctx(ctx); - pgoff_t pgoff; user_uffdio_register = (struct uffdio_register __user *) arg; @@ -1484,28 +1482,17 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, vma_end = min(end, vma->vm_end); new_flags = (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags; - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - prev = vma_merge(&vmi, mm, prev, start, vma_end, new_flags, - vma->anon_vma, vma->vm_file, pgoff, - vma_policy(vma), - ((struct vm_userfaultfd_ctx){ ctx }), - anon_vma_name(vma)); - if (prev) { - /* vma_merge() invalidated the mas */ - vma = prev; - goto next; - } - if (vma->vm_start < start) { - ret = split_vma(&vmi, vma, start, 1); - if (ret) - break; - } - if (vma->vm_end > end) { - ret = split_vma(&vmi, vma, end, 0); - if (ret) - break; + prev = vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, + new_flags, + (struct vm_userfaultfd_ctx){ctx}); + if (IS_ERR(prev)) { + ret = PTR_ERR(prev); + break; } - next: + + if (prev) + vma = prev; /* vma_merge() invalidated the mas */ + /* * In the vma_merge() successful mprotect-like case 8: * the next vma was merged into the current one and @@ -1568,7 +1555,6 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, const void __user *buf = (void __user *)arg; struct vma_iterator vmi; bool wp_async = userfaultfd_wp_async_ctx(ctx); - pgoff_t pgoff; ret = -EFAULT; if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister))) @@ -1671,26 +1657,15 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx, uffd_wp_range(vma, start, vma_end - start, false); new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS; - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - prev = vma_merge(&vmi, mm, prev, start, vma_end, new_flags, - vma->anon_vma, vma->vm_file, pgoff, - vma_policy(vma), - NULL_VM_UFFD_CTX, anon_vma_name(vma)); - if (prev) { - vma = prev; - goto next; - } - if (vma->vm_start < start) { - ret = split_vma(&vmi, vma, start, 1); - if (ret) - break; - } - if (vma->vm_end > end) { - ret = split_vma(&vmi, vma, end, 0); - if (ret) - break; + prev = vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, + new_flags, NULL_VM_UFFD_CTX); + if (IS_ERR(prev)) { + ret = PTR_ERR(prev); + break; } - next: + + if (prev) + vma = prev; /* * In the vma_merge() successful mprotect-like case 8: * the next vma was merged into the current one and diff --git a/include/linux/mm.h b/include/linux/mm.h index a7b667786cde..83ee1f35febe 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3253,6 +3253,66 @@ extern struct vm_area_struct *copy_vma(struct vm_area_struct **, unsigned long addr, unsigned long len, pgoff_t pgoff, bool *need_rmap_locks); extern void exit_mmap(struct mm_struct *); +struct vm_area_struct *vma_modify(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + unsigned long vm_flags, + struct mempolicy *policy, + struct vm_userfaultfd_ctx uffd_ctx, + struct anon_vma_name *anon_name); + +/* We are about to modify the VMA's flags. */ +static inline struct vm_area_struct +*vma_modify_flags(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + unsigned long new_flags) +{ + return vma_modify(vmi, prev, vma, start, end, new_flags, + vma_policy(vma), vma->vm_userfaultfd_ctx, + anon_vma_name(vma)); +} + +/* We are about to modify the VMA's flags and/or anon_name. */ +static inline struct vm_area_struct +*vma_modify_flags_name(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, + unsigned long end, + unsigned long new_flags, + struct anon_vma_name *new_name) +{ + return vma_modify(vmi, prev, vma, start, end, new_flags, + vma_policy(vma), vma->vm_userfaultfd_ctx, new_name); +} + +/* We are about to modify the VMA's memory policy. */ +static inline struct vm_area_struct +*vma_modify_policy(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct mempolicy *new_pol) +{ + return vma_modify(vmi, prev, vma, start, end, vma->vm_flags, + new_pol, vma->vm_userfaultfd_ctx, anon_vma_name(vma)); +} + +/* We are about to modify the VMA's flags and/or uffd context. */ +static inline struct vm_area_struct +*vma_modify_flags_uffd(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + unsigned long new_flags, + struct vm_userfaultfd_ctx new_ctx) +{ + return vma_modify(vmi, prev, vma, start, end, new_flags, + vma_policy(vma), new_ctx, anon_vma_name(vma)); +} static inline int check_data_rlimit(unsigned long rlim, unsigned long new, diff --git a/mm/madvise.c b/mm/madvise.c index a4a20de50494..801d3c1bb7b3 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -141,7 +141,7 @@ static int madvise_update_vma(struct vm_area_struct *vma, { struct mm_struct *mm = vma->vm_mm; int error; - pgoff_t pgoff; + struct vm_area_struct *merged; VMA_ITERATOR(vmi, mm, start); if (new_flags == vma->vm_flags && anon_vma_name_eq(anon_vma_name(vma), anon_name)) { @@ -149,30 +149,16 @@ static int madvise_update_vma(struct vm_area_struct *vma, return 0; } - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *prev = vma_merge(&vmi, mm, *prev, start, end, new_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, anon_name); - if (*prev) { - vma = *prev; - goto success; - } - - *prev = vma; - - if (start != vma->vm_start) { - error = split_vma(&vmi, vma, start, 1); - if (error) - return error; - } + merged = vma_modify_flags_name(&vmi, *prev, vma, start, end, new_flags, + anon_name); + if (IS_ERR(merged)) + return PTR_ERR(merged); - if (end != vma->vm_end) { - error = split_vma(&vmi, vma, end, 0); - if (error) - return error; - } + if (merged) + vma = *prev = merged; + else + *prev = vma; -success: /* vm_flags is protected by the mmap_lock held in write mode. */ vma_start_write(vma); vm_flags_reset(vma, new_flags); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b01922e88548..6b2e99db6dd5 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -786,8 +786,6 @@ static int mbind_range(struct vma_iterator *vmi, struct vm_area_struct *vma, { struct vm_area_struct *merged; unsigned long vmstart, vmend; - pgoff_t pgoff; - int err; vmend = min(end, vma->vm_end); if (start > vma->vm_start) { @@ -802,27 +800,15 @@ static int mbind_range(struct vma_iterator *vmi, struct vm_area_struct *vma, return 0; } - pgoff = vma->vm_pgoff + ((vmstart - vma->vm_start) >> PAGE_SHIFT); - merged = vma_merge(vmi, vma->vm_mm, *prev, vmstart, vmend, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, new_pol, - vma->vm_userfaultfd_ctx, anon_vma_name(vma)); + merged = vma_modify_policy(vmi, *prev, vma, vmstart, vmend, new_pol); + if (IS_ERR(merged)) + return PTR_ERR(merged); + if (merged) { *prev = merged; return vma_replace_policy(merged, new_pol); } - if (vma->vm_start != vmstart) { - err = split_vma(vmi, vma, vmstart, 1); - if (err) - return err; - } - - if (vma->vm_end != vmend) { - err = split_vma(vmi, vma, vmend, 0); - if (err) - return err; - } - *prev = vma; return vma_replace_policy(vma, new_pol); } diff --git a/mm/mlock.c b/mm/mlock.c index 42b6865f8f82..ae83a33c387e 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -476,10 +476,10 @@ static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, unsigned long end, vm_flags_t newflags) { struct mm_struct *mm = vma->vm_mm; - pgoff_t pgoff; int nr_pages; int ret = 0; vm_flags_t oldflags = vma->vm_flags; + struct vm_area_struct *merged; if (newflags == oldflags || (oldflags & VM_SPECIAL) || is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm) || @@ -487,28 +487,15 @@ static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma, /* don't set VM_LOCKED or VM_LOCKONFAULT and don't count */ goto out; - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *prev = vma_merge(vmi, mm, *prev, start, end, newflags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, anon_vma_name(vma)); - if (*prev) { - vma = *prev; - goto success; - } - - if (start != vma->vm_start) { - ret = split_vma(vmi, vma, start, 1); - if (ret) - goto out; + merged = vma_modify_flags(vmi, *prev, vma, start, end, newflags); + if (IS_ERR(merged)) { + ret = PTR_ERR(merged); + goto out; } - if (end != vma->vm_end) { - ret = split_vma(vmi, vma, end, 0); - if (ret) - goto out; - } + if (merged) + vma = *prev = merged; -success: /* * Keep track of amount of locked VM. */ diff --git a/mm/mmap.c b/mm/mmap.c index 673429ee8a9e..22d968affc07 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2437,6 +2437,51 @@ int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, return __split_vma(vmi, vma, addr, new_below); } +/* + * We are about to modify one or multiple of a VMA's flags, policy, userfaultfd + * context and anonymous VMA name within the range [start, end). + * + * As a result, we might be able to merge the newly modified VMA range with an + * adjacent VMA with identical properties. + * + * If no merge is possible and the range does not span the entirety of the VMA, + * we then need to split the VMA to accommodate the change. + */ +struct vm_area_struct *vma_modify(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, unsigned long end, + unsigned long vm_flags, + struct mempolicy *policy, + struct vm_userfaultfd_ctx uffd_ctx, + struct anon_vma_name *anon_name) +{ + pgoff_t pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); + struct vm_area_struct *merged; + + merged = vma_merge(vmi, vma->vm_mm, prev, start, end, vm_flags, + vma->anon_vma, vma->vm_file, pgoff, policy, + uffd_ctx, anon_name); + if (merged) + return merged; + + if (vma->vm_start < start) { + int err = split_vma(vmi, vma, start, 1); + + if (err) + return ERR_PTR(err); + } + + if (vma->vm_end > end) { + int err = split_vma(vmi, vma, end, 0); + + if (err) + return ERR_PTR(err); + } + + return NULL; +} + /* * do_vmi_align_munmap() - munmap the aligned region from @start to @end. * @vmi: The vma iterator diff --git a/mm/mprotect.c b/mm/mprotect.c index b94fbb45d5c7..6f85d99682ab 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -581,7 +581,7 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb, long nrpages = (end - start) >> PAGE_SHIFT; unsigned int mm_cp_flags = 0; unsigned long charged = 0; - pgoff_t pgoff; + struct vm_area_struct *merged; int error; if (newflags == oldflags) { @@ -625,34 +625,19 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb, } } - /* - * First try to merge with previous and/or next vma. - */ - pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); - *pprev = vma_merge(vmi, mm, *pprev, start, end, newflags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, anon_vma_name(vma)); - if (*pprev) { - vma = *pprev; - VM_WARN_ON((vma->vm_flags ^ newflags) & ~VM_SOFTDIRTY); - goto success; + merged = vma_modify_flags(vmi, *pprev, vma, start, end, newflags); + if (IS_ERR(merged)) { + error = PTR_ERR(merged); + goto fail; } - *pprev = vma; - - if (start != vma->vm_start) { - error = split_vma(vmi, vma, start, 1); - if (error) - goto fail; - } - - if (end != vma->vm_end) { - error = split_vma(vmi, vma, end, 0); - if (error) - goto fail; + if (merged) { + vma = *pprev = merged; + VM_WARN_ON((vma->vm_flags ^ newflags) & ~VM_SOFTDIRTY); + } else { + *pprev = vma; } -success: /* * vm_flags and vm_page_prot are protected by the mmap_lock * held in write mode. From patchwork Mon Oct 9 20:53:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Stoakes X-Patchwork-Id: 13414424 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AAA42CD6136 for ; Mon, 9 Oct 2023 20:54:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1377989AbjJIUyD (ORCPT ); Mon, 9 Oct 2023 16:54:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378102AbjJIUxm (ORCPT ); Mon, 9 Oct 2023 16:53:42 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D67BCF; Mon, 9 Oct 2023 13:53:39 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-3232be274a0so3649600f8f.1; Mon, 09 Oct 2023 13:53:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696884817; x=1697489617; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TNmdoeRWtzhEBIdrRfXv8hL/K0SAgSJWqJyZUiMnE00=; b=EpqjRpfyiiX7wHKgfKsbcl2biJq1/1RXqVPajYmQau6r/EuHInFB2i4eqyIbY2kF1N S+DJCpIpDjZtVfhoi0SLXY30mR6a7cL/1dmNRbyOcuusxeZ5eEUkM5E1HwhpksOMdZQ0 Q3pwjAUuFOaqbfaGkmEkfb7wvndJ7EHAshyDuF8HKUyfS6jp+MerjJfbln1FH6iNz/88 tqt9QB0NnQRNpNsdxOOcd+BupfRUdBiO1QqkaRoMciMBGMqGpBSneTeaH+5mQEvrCn4b LvVsplgV3DzNZu0zyC6dNcZ8tYDYBm9mMDEIqY5OpgVJBrZI9tFcrpWS2MI5MSLcS5SH RW/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696884817; x=1697489617; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TNmdoeRWtzhEBIdrRfXv8hL/K0SAgSJWqJyZUiMnE00=; b=Jgw59/3+K5Qvx7s722bcTnNMs6cB8aY8x7sbPnbtSRSaqPiDu80JGxc2MkudIEveZa 7UPZtRXpw/mU2tCvb7kYfR1qsLG18TY8yPN237Ej+1+jqED4b4QTSPXHZFQsbFbBAVkY UYU44RBl38gF70BIOcPHXF5VKgC6LWlNs/zImGlEbV+atfDdyay44GpnuFrO+yN5+yw5 9PAURAxdceL4gxsRJwNiiy72qa4JMwsXog/zVDYtYuhtH2V1qHWPxTBn+O4YMls50/EF t+dnAd+MESglg5UZiOYwxMLwUHatI3TNXYqzSDmKzaB8NsqWjabejXJlbL+2DgaOHDfL krMA== X-Gm-Message-State: AOJu0Yw5gN47PLJgl+0qdnoZOd1S+w6ARGi02QV59bEzk0+/UCKX9dtL 05Hq8nwJRE48JLt9hpp5l6E= X-Google-Smtp-Source: AGHT+IGxaxbfOsmbWfYeIketHcaygFp0L6cqjHa1Rm6inszqpIbIyR7FdF/1P3t2wIMfyeWkX0LuMQ== X-Received: by 2002:a05:6000:3c3:b0:32c:d29c:2f77 with SMTP id b3-20020a05600003c300b0032cd29c2f77mr40326wrg.1.1696884817261; Mon, 09 Oct 2023 13:53:37 -0700 (PDT) Received: from lucifer.home ([2a00:23c5:dc8c:8701:1663:9a35:5a7b:1d76]) by smtp.googlemail.com with ESMTPSA id l2-20020a5d4802000000b0031fe0576460sm10578130wrq.11.2023.10.09.13.53.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 13:53:36 -0700 (PDT) From: Lorenzo Stoakes To: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrew Morton , Alexander Viro , Christian Brauner Cc: "=Liam R . Howlett" , Vlastimil Babka , linux-fsdevel@vger.kernel.org, Lorenzo Stoakes Subject: [PATCH v2 3/5] mm: make vma_merge() and split_vma() internal Date: Mon, 9 Oct 2023 21:53:18 +0100 Message-ID: <31d2c79f7a3bca03d4a4c95e98d9a27cb1f99bf1.1696884493.git.lstoakes@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Now the common pattern of - attempting a merge via vma_merge() and should this fail splitting VMAs via split_vma() - has been abstracted, the former can be placed into mm/internal.h and the latter made static. In addition, the split_vma() nommu variant also need not be exported. Reviewed-by: Vlastimil Babka Signed-off-by: Lorenzo Stoakes --- include/linux/mm.h | 9 --------- mm/internal.h | 9 +++++++++ mm/mmap.c | 8 ++++---- mm/nommu.c | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 83ee1f35febe..74d7547ffb70 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3237,16 +3237,7 @@ extern int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma, struct vm_area_struct *next); extern int vma_shrink(struct vma_iterator *vmi, struct vm_area_struct *vma, unsigned long start, unsigned long end, pgoff_t pgoff); -extern struct vm_area_struct *vma_merge(struct vma_iterator *vmi, - struct mm_struct *, struct vm_area_struct *prev, unsigned long addr, - unsigned long end, unsigned long vm_flags, struct anon_vma *, - struct file *, pgoff_t, struct mempolicy *, struct vm_userfaultfd_ctx, - struct anon_vma_name *); extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); -extern int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *, - unsigned long addr, int new_below); -extern int split_vma(struct vma_iterator *vmi, struct vm_area_struct *, - unsigned long addr, int new_below); extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *); extern void unlink_file_vma(struct vm_area_struct *); extern struct vm_area_struct *copy_vma(struct vm_area_struct **, diff --git a/mm/internal.h b/mm/internal.h index 3a72975425bb..ddaeb9f2d9d7 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1011,6 +1011,15 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd, unsigned int flags); +/* + * mm/mmap.c + */ +struct vm_area_struct *vma_merge(struct vma_iterator *vmi, + struct mm_struct *, struct vm_area_struct *prev, unsigned long addr, + unsigned long end, unsigned long vm_flags, struct anon_vma *, + struct file *, pgoff_t, struct mempolicy *, struct vm_userfaultfd_ctx, + struct anon_vma_name *); + enum { /* mark page accessed */ FOLL_TOUCH = 1 << 16, diff --git a/mm/mmap.c b/mm/mmap.c index 22d968affc07..17c0dcfb1527 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2346,8 +2346,8 @@ static void unmap_region(struct mm_struct *mm, struct ma_state *mas, * has already been checked or doesn't make sense to fail. * VMA Iterator will point to the end VMA. */ -int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, - unsigned long addr, int new_below) +static int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, + unsigned long addr, int new_below) { struct vma_prepare vp; struct vm_area_struct *new; @@ -2428,8 +2428,8 @@ int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, * Split a vma into two pieces at address 'addr', a new vma is allocated * either for the first part or the tail. */ -int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, - unsigned long addr, int new_below) +static int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, + unsigned long addr, int new_below) { if (vma->vm_mm->map_count >= sysctl_max_map_count) return -ENOMEM; diff --git a/mm/nommu.c b/mm/nommu.c index f9553579389b..fc4afe924ad5 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1305,8 +1305,8 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) * split a vma into two pieces at address 'addr', a new vma is allocated either * for the first part or the tail. */ -int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, - unsigned long addr, int new_below) +static int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, + unsigned long addr, int new_below) { struct vm_area_struct *new; struct vm_region *region; From patchwork Mon Oct 9 20:53:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Stoakes X-Patchwork-Id: 13414427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5143DCD612F for ; Mon, 9 Oct 2023 20:54:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378146AbjJIUyJ (ORCPT ); Mon, 9 Oct 2023 16:54:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57166 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378131AbjJIUxv (ORCPT ); Mon, 9 Oct 2023 16:53:51 -0400 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 56A56DA; Mon, 9 Oct 2023 13:53:40 -0700 (PDT) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-405524e6768so48373465e9.2; Mon, 09 Oct 2023 13:53:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696884819; x=1697489619; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=peKTa5JCQROacC2rkKD/EMjKt2/PWD6RJuctYYclWYk=; b=mfgEsJ+AeOapng4RmufLLmrtrfGoffxSMqILk521+uVLk+EgUUV2gYuK9mRLMGD2if 9JLL34I53sVmrtRdYpERy5MvOT6Fe+7MMnQpzTOnebBHFtp/iPtUbDkRf6C6ddUL03Nb nk0DMLpz/cPxPZqXVG4JWZ8o2Kha7fpPocLEwzG9nmt/7igq/ySf6pXO/oDSBYl2i5Al dxNw6a8HaAKFuRpunZ+3frBXSSPfDjbAnxPT/+mtwoO1eqtYVb3MxcJSQ4nMgTs2XGpt 4/jIk926E2SPZ/lEaKQkeChYfzFtUhOm0sUt0c/CeYyP4BKjAH5F+YyXR6vvxRw3p3eM n1Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696884819; x=1697489619; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=peKTa5JCQROacC2rkKD/EMjKt2/PWD6RJuctYYclWYk=; b=vXznFh2IR2voOis+cJ5IR3hqPUBpjzVYmLaZAPsHg6julclyQeQuf90OxWIPxkeuRn z6Ycu40UQrjOBH4z2dn2z8Z9lnG2XVLtUwjdpc/2S6+u4Yy3UGkBqyx77dT7LCpXYb3A /9Czid9903he/+ME/jJ4aw3qE6FtDCtZdsYcDAvB8kuYmuCQ3lwnL2O8mSc/7JFOKrLS hfIHJwKEAxOy2FRdV2g9kMlRud6U7klOoesJDdmOtXZY6d4gHbiXUxnjtpLr6u3u5vSz UTk3xCzTc8QvXCDR3QEXqNOHrfdIA1cVcLf498IHX6p9gPRyw54T8d2u6DoRumE+bQM5 61Cg== X-Gm-Message-State: AOJu0YxtAUgoPV13T2y+eBLECIuvDBFnbpUN22RiukCD3MAzQP45Zuic FaMbjvJJzb08w49G+NbP+Fg= X-Google-Smtp-Source: AGHT+IECOr/NuIGQT0xwu1GNnQ3mzgM7UNNwWg6rN1KgZwpIM+meh3t/4/xhAlA92IoCFh4rHNSa8g== X-Received: by 2002:adf:a4c1:0:b0:32c:a9ac:2bc1 with SMTP id h1-20020adfa4c1000000b0032ca9ac2bc1mr216695wrb.63.1696884818605; Mon, 09 Oct 2023 13:53:38 -0700 (PDT) Received: from lucifer.home ([2a00:23c5:dc8c:8701:1663:9a35:5a7b:1d76]) by smtp.googlemail.com with ESMTPSA id l2-20020a5d4802000000b0031fe0576460sm10578130wrq.11.2023.10.09.13.53.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 13:53:37 -0700 (PDT) From: Lorenzo Stoakes To: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrew Morton , Alexander Viro , Christian Brauner Cc: "=Liam R . Howlett" , Vlastimil Babka , linux-fsdevel@vger.kernel.org, Lorenzo Stoakes Subject: [PATCH v2 4/5] mm: abstract merge for new VMAs into vma_merge_new_vma() Date: Mon, 9 Oct 2023 21:53:19 +0100 Message-ID: <8525290591267805ffabf8a31b53f0290a6a4276.1696884493.git.lstoakes@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Only in mmap_region() and copy_vma() do we attempt to merge VMAs which occupy entirely new regions of virtual memory. We can abstract this logic and make the intent of this invocations of it completely explicit, rather than invoking vma_merge() with an inscrutable wall of parameters. This also paves the way for a simplification of the core vma_merge() implementation, as we seek to make it entirely an implementation detail. Note that on mmap_region(), VMA fields are initialised to zero, so we can simply reference these rather than explicitly specifying NULL. Reviewed-by: Vlastimil Babka Signed-off-by: Lorenzo Stoakes --- mm/mmap.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 17c0dcfb1527..33aafd23823b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2482,6 +2482,22 @@ struct vm_area_struct *vma_modify(struct vma_iterator *vmi, return NULL; } +/* + * Attempt to merge a newly mapped VMA with those adjacent to it. The caller + * must ensure that [start, end) does not overlap any existing VMA. + */ +static struct vm_area_struct *vma_merge_new_vma(struct vma_iterator *vmi, + struct vm_area_struct *prev, + struct vm_area_struct *vma, + unsigned long start, + unsigned long end, + pgoff_t pgoff) +{ + return vma_merge(vmi, vma->vm_mm, prev, start, end, vma->vm_flags, + vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), + vma->vm_userfaultfd_ctx, anon_vma_name(vma)); +} + /* * do_vmi_align_munmap() - munmap the aligned region from @start to @end. * @vmi: The vma iterator @@ -2837,10 +2853,9 @@ unsigned long mmap_region(struct file *file, unsigned long addr, * vma again as we may succeed this time. */ if (unlikely(vm_flags != vma->vm_flags && prev)) { - merge = vma_merge(&vmi, mm, prev, vma->vm_start, - vma->vm_end, vma->vm_flags, NULL, - vma->vm_file, vma->vm_pgoff, NULL, - NULL_VM_UFFD_CTX, NULL); + merge = vma_merge_new_vma(&vmi, prev, vma, + vma->vm_start, vma->vm_end, + pgoff); if (merge) { /* * ->mmap() can change vma->vm_file and fput @@ -3382,9 +3397,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, if (new_vma && new_vma->vm_start < addr + len) return NULL; /* should never get here */ - new_vma = vma_merge(&vmi, mm, prev, addr, addr + len, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, anon_vma_name(vma)); + new_vma = vma_merge_new_vma(&vmi, prev, vma, addr, addr + len, pgoff); if (new_vma) { /* * Source vma may have been merged into new_vma From patchwork Mon Oct 9 20:53:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Stoakes X-Patchwork-Id: 13414425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE0A9CD612F for ; Mon, 9 Oct 2023 20:54:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378152AbjJIUyE (ORCPT ); Mon, 9 Oct 2023 16:54:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57248 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1378147AbjJIUxw (ORCPT ); Mon, 9 Oct 2023 16:53:52 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BF3C5B0; Mon, 9 Oct 2023 13:53:41 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-32615eaa312so4575814f8f.2; Mon, 09 Oct 2023 13:53:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696884820; x=1697489620; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xL574zJuwTg3rbZ38h4Jjm16YvUMoLxu5gzcSq0qQog=; b=dbvlfFcWXQ6iaB0eGPBARCf/16J/NcSoekYzPmQFSHACh24Ne6J1eUMT6riokp5eI3 V1nxGfackS0KshmDqeA7WXLJymGtoCeibTAFKbtyH10tvwKQ/HCLeOL4AWnIbxPcBblG Taw4E+9JFCGwfZLb0q8WhHlNG/mjCYikIKFlVSvfF9W5hS2QWEVBfdLxsLxPrWndvNb7 kQrGcJZqBB8AUq4Wv9QIVigTnj47zAuZTOuW+mxYN/gd0d1rmitBzhu15HD5TZSzZ5r/ To3bFKEFC2HrOt44+82Y8DpwhnCsxGvnVmC9hcMfk3CW2n7deOhIx10p3Z77clA29qTj SL6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696884820; x=1697489620; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xL574zJuwTg3rbZ38h4Jjm16YvUMoLxu5gzcSq0qQog=; b=ZLvcBRKOV/rIzdD5yJrae6biTqwdVPddd7sILpe0ULT8H3vpytj4E5WVa1euHEnwxz pjF3lA2tU9uQ+k4EEvSwHCNj19M5tH9FqfZMrvE2fm8MyILeNSTS2iZS7/B4N25ZvvVH e2shW6KgFPdV6Ztbs+/tu/NlEkNjXSMqa5LGEB8RCHkVZBhxa20vuTtpc3lV/yclZ+2M iiRTgcXouF4n63jNy5V8c5WOwucyeis63LMm4WXm8v6xdIFQ8EmqTNOBJoQLP2t7K2zi n/GiWnkPW/hlX+1Qi53LH/WhJLf2riFwhhbY4r6n7lQ1DiZJ3WNCrrPQ1ZxfZ8MCGaRD FBig== X-Gm-Message-State: AOJu0YzUhFWGME0DFoDxEUV60/EzNdfGLhs4noE0STBg88zl8yxrdMs4 SzG/ctxX3bfExWMatNUkVivT6iiQPsg= X-Google-Smtp-Source: AGHT+IEZcDJXfUk/m4asVym6HC8MzhKstd/QCfQCxF3CdaRPkCYRP2UAGVNJPPmMrmT3c3m/Jt2IXw== X-Received: by 2002:adf:e6ce:0:b0:31f:b7b2:d4e1 with SMTP id y14-20020adfe6ce000000b0031fb7b2d4e1mr14332666wrm.20.1696884819954; Mon, 09 Oct 2023 13:53:39 -0700 (PDT) Received: from lucifer.home ([2a00:23c5:dc8c:8701:1663:9a35:5a7b:1d76]) by smtp.googlemail.com with ESMTPSA id l2-20020a5d4802000000b0031fe0576460sm10578130wrq.11.2023.10.09.13.53.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 13:53:39 -0700 (PDT) From: Lorenzo Stoakes To: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrew Morton , Alexander Viro , Christian Brauner Cc: "=Liam R . Howlett" , Vlastimil Babka , linux-fsdevel@vger.kernel.org, Lorenzo Stoakes Subject: [PATCH v2 5/5] mm: abstract VMA merge and extend into vma_merge_extend() helper Date: Mon, 9 Oct 2023 21:53:20 +0100 Message-ID: X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org mremap uses vma_merge() in the case where a VMA needs to be extended. This can be significantly simplified and abstracted. This makes it far easier to understand what the actual function is doing, avoids future mistakes in use of the confusing vma_merge() function and importantly allows us to make future changes to how vma_merge() is implemented by knowing explicitly which merge cases each invocation uses. Note that in the mremap() extend case, we perform this merge only when old_len == vma->vm_end - addr. The extension_start, i.e. the start of the extended portion of the VMA is equal to addr + old_len, i.e. vma->vm_end. With this refactoring, vma_merge() is no longer required anywhere except mm/mmap.c, so mark it static. Reviewed-by: Vlastimil Babka Signed-off-by: Lorenzo Stoakes --- mm/internal.h | 8 +++----- mm/mmap.c | 31 ++++++++++++++++++++++++------- mm/mremap.c | 30 +++++++++++++----------------- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index ddaeb9f2d9d7..6fa722b07a94 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1014,11 +1014,9 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, /* * mm/mmap.c */ -struct vm_area_struct *vma_merge(struct vma_iterator *vmi, - struct mm_struct *, struct vm_area_struct *prev, unsigned long addr, - unsigned long end, unsigned long vm_flags, struct anon_vma *, - struct file *, pgoff_t, struct mempolicy *, struct vm_userfaultfd_ctx, - struct anon_vma_name *); +struct vm_area_struct *vma_merge_extend(struct vma_iterator *vmi, + struct vm_area_struct *vma, + unsigned long delta); enum { /* mark page accessed */ diff --git a/mm/mmap.c b/mm/mmap.c index 33aafd23823b..200319bf3292 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -860,13 +860,13 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, * **** is not represented - it will be merged and the vma containing the * area is returned, or the function will return NULL */ -struct vm_area_struct *vma_merge(struct vma_iterator *vmi, struct mm_struct *mm, - struct vm_area_struct *prev, unsigned long addr, - unsigned long end, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, - pgoff_t pgoff, struct mempolicy *policy, - struct vm_userfaultfd_ctx vm_userfaultfd_ctx, - struct anon_vma_name *anon_name) +static struct vm_area_struct +*vma_merge(struct vma_iterator *vmi, struct mm_struct *mm, + struct vm_area_struct *prev, unsigned long addr, unsigned long end, + unsigned long vm_flags, struct anon_vma *anon_vma, struct file *file, + pgoff_t pgoff, struct mempolicy *policy, + struct vm_userfaultfd_ctx vm_userfaultfd_ctx, + struct anon_vma_name *anon_name) { struct vm_area_struct *curr, *next, *res; struct vm_area_struct *vma, *adjust, *remove, *remove2; @@ -2498,6 +2498,23 @@ static struct vm_area_struct *vma_merge_new_vma(struct vma_iterator *vmi, vma->vm_userfaultfd_ctx, anon_vma_name(vma)); } +/* + * Expand vma by delta bytes, potentially merging with an immediately adjacent + * VMA with identical properties. + */ +struct vm_area_struct *vma_merge_extend(struct vma_iterator *vmi, + struct vm_area_struct *vma, + unsigned long delta) +{ + pgoff_t pgoff = vma->vm_pgoff + vma_pages(vma); + + /* vma is specified as prev, so case 1 or 2 will apply. */ + return vma_merge(vmi, vma->vm_mm, vma, vma->vm_end, vma->vm_end + delta, + vma->vm_flags, vma->anon_vma, vma->vm_file, pgoff, + vma_policy(vma), vma->vm_userfaultfd_ctx, + anon_vma_name(vma)); +} + /* * do_vmi_align_munmap() - munmap the aligned region from @start to @end. * @vmi: The vma iterator diff --git a/mm/mremap.c b/mm/mremap.c index ce8a23ef325a..38d98465f3d8 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -1096,14 +1096,12 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, /* old_len exactly to the end of the area.. */ if (old_len == vma->vm_end - addr) { + unsigned long delta = new_len - old_len; + /* can we just expand the current mapping? */ - if (vma_expandable(vma, new_len - old_len)) { - long pages = (new_len - old_len) >> PAGE_SHIFT; - unsigned long extension_start = addr + old_len; - unsigned long extension_end = addr + new_len; - pgoff_t extension_pgoff = vma->vm_pgoff + - ((extension_start - vma->vm_start) >> PAGE_SHIFT); - VMA_ITERATOR(vmi, mm, extension_start); + if (vma_expandable(vma, delta)) { + long pages = delta >> PAGE_SHIFT; + VMA_ITERATOR(vmi, mm, vma->vm_end); long charged = 0; if (vma->vm_flags & VM_ACCOUNT) { @@ -1115,17 +1113,15 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, } /* - * Function vma_merge() is called on the extension we - * are adding to the already existing vma, vma_merge() - * will merge this extension with the already existing - * vma (expand operation itself) and possibly also with - * the next vma if it becomes adjacent to the expanded - * vma and otherwise compatible. + * Function vma_merge_extend() is called on the + * extension we are adding to the already existing vma, + * vma_merge_extend() will merge this extension with the + * already existing vma (expand operation itself) and + * possibly also with the next vma if it becomes + * adjacent to the expanded vma and otherwise + * compatible. */ - vma = vma_merge(&vmi, mm, vma, extension_start, - extension_end, vma->vm_flags, vma->anon_vma, - vma->vm_file, extension_pgoff, vma_policy(vma), - vma->vm_userfaultfd_ctx, anon_vma_name(vma)); + vma = vma_merge_extend(&vmi, vma, delta); if (!vma) { vm_unacct_memory(charged); ret = -ENOMEM;