From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D2C438BF6C; Fri, 20 Mar 2026 22:40:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046409; cv=none; b=GFwJ4EsLCkYY8CBK3USqOcffptTwHA95TWNn6qKQSVcETbUkGdLnsmsi8BfNIWW8qR5N0mzePOlh92d8v1mSkPvAswVSTTDEJDiArVQCdFYLEWczJBVLUfxaKBnJnKTx1NO0SiPCCYQgCk0mGTdzWkrDQqjm9cSsiQ5SVWl6bRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046409; c=relaxed/simple; bh=/eFcILNrrDL/FJ/GXYtQOFiMhhVt3ls4GxXx41zEl5w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SmreIDb/9S2hDosEt7BcPf760cR0vXxT4anRh5XkmAw79YRsOd27p8ebeQanmBmB16ysMyzRy7eEKOaU38wwzUlWur1dfMezZh0hWR+baHCJnYaVS55jVhkpWkdSIjCrnDIwaEH+mUvm0FjrfMRC7RPC3u238Rk5AR9YC+HACHA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jDB8yu+3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jDB8yu+3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8D149C4CEF7; Fri, 20 Mar 2026 22:40:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046409; bh=/eFcILNrrDL/FJ/GXYtQOFiMhhVt3ls4GxXx41zEl5w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jDB8yu+35VLB8nyurcTNRGGilntgo6oVbhQafoq0MRcauH/fOPjyWJ/9/zVdfGmBN vuRST5X0S+sViZmfOc9I7wAbOuIMN4lR2b2d3Tm7X73EFp6Xy00nxti3OFIt76r1eP J4Ynw6B3Ljyno4dxdxTsulEiUf55ckUOTPrkvmK8E2mCH/wyKm8FKpDkrY6mEP9n0u AhDhC1TUUNHul6hnVWr/4UUSnbAGBke2pU6R6xwdBwFTXK0vnEQYoGhAYe9qjn/09f lxyO96oKQvZG47vM2xw7C/0T7NKSfRGrAh5Hc2DuJ9i1RMGy/rbe2VCQ3Syx97ceMU GByQXcqolO1zg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 01/21] mm: various small mmap_prepare cleanups Date: Fri, 20 Mar 2026 22:39:27 +0000 Message-ID: <99f408e4694f44ab12bdc55fe0bd9685d3bd1117.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rather than passing arbitrary fields, pass a vm_area_desc pointer to mmap prepare functions to mmap prepare, and an action and vma pointer to mmap complete in order to put all the action-specific logic in the function actually doing the work. Additionally, allow mmap prepare functions to return an error so we can error out as soon as possible if there is something logically incorrect in the input. Update remap_pfn_range_prepare() to properly check the input range for the CoW case. Also remove io_remap_pfn_range_complete(), as we can simply set up the fields correctly in io_remap_pfn_range_prepare() and use remap_pfn_range_complete() for this. While we're here, make remap_pfn_range_prepare_vma() a little neater, and pass mmap_action directly to call_action_complete(). Then, update compat_vma_mmap() to perform its logic directly, as __compat_vma_map() is not used by anything so we don't need to export it. Also update compat_vma_mmap() to use vfs_mmap_prepare() rather than calling the mmap_prepare op directly. Finally, update the VMA userland tests to reflect the changes. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- include/linux/fs.h | 2 - include/linux/mm.h | 7 +- mm/internal.h | 32 ++++---- mm/memory.c | 45 +++++++---- mm/util.c | 121 +++++++++++++----------------- mm/vma.c | 24 +++--- tools/testing/vma/include/dup.h | 7 +- tools/testing/vma/include/stubs.h | 8 +- 8 files changed, 126 insertions(+), 120 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 8b3dd145b25e..a2628a12bd2b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2058,8 +2058,6 @@ static inline bool can_mmap_file(struct file *file) return true; } =20 -int __compat_vma_mmap(const struct file_operations *f_op, - struct file *file, struct vm_area_struct *vma); int compat_vma_mmap(struct file *file, struct vm_area_struct *vma); =20 static inline int vfs_mmap(struct file *file, struct vm_area_struct *vma) diff --git a/include/linux/mm.h b/include/linux/mm.h index 42cc40aa63d9..1e63b3a44a47 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4320,10 +4320,9 @@ static inline void mmap_action_ioremap_full(struct v= m_area_desc *desc, mmap_action_ioremap(desc, desc->start, start_pfn, vma_desc_size(desc)); } =20 -void mmap_action_prepare(struct mmap_action *action, - struct vm_area_desc *desc); -int mmap_action_complete(struct mmap_action *action, - struct vm_area_struct *vma); +int mmap_action_prepare(struct vm_area_desc *desc); +int mmap_action_complete(struct vm_area_struct *vma, + struct mmap_action *action); =20 /* Look up the first VMA which exactly match the interval vm_start ... vm_= end */ static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm, diff --git a/mm/internal.h b/mm/internal.h index 708d240b4198..0256ca44115a 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1793,26 +1793,28 @@ int walk_page_range_debug(struct mm_struct *mm, uns= igned long start, void dup_mm_exe_file(struct mm_struct *mm, struct mm_struct *oldmm); int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm); =20 -void remap_pfn_range_prepare(struct vm_area_desc *desc, unsigned long pfn); -int remap_pfn_range_complete(struct vm_area_struct *vma, unsigned long add= r, - unsigned long pfn, unsigned long size, pgprot_t pgprot); +int remap_pfn_range_prepare(struct vm_area_desc *desc); +int remap_pfn_range_complete(struct vm_area_struct *vma, + struct mmap_action *action); =20 -static inline void io_remap_pfn_range_prepare(struct vm_area_desc *desc, - unsigned long orig_pfn, unsigned long size) +static inline int io_remap_pfn_range_prepare(struct vm_area_desc *desc) { + struct mmap_action *action =3D &desc->action; + const unsigned long orig_pfn =3D action->remap.start_pfn; + const pgprot_t orig_pgprot =3D action->remap.pgprot; + const unsigned long size =3D action->remap.size; const unsigned long pfn =3D io_remap_pfn_range_pfn(orig_pfn, size); + int err; =20 - return remap_pfn_range_prepare(desc, pfn); -} + action->remap.start_pfn =3D pfn; + action->remap.pgprot =3D pgprot_decrypted(orig_pgprot); + err =3D remap_pfn_range_prepare(desc); + if (err) + return err; =20 -static inline int io_remap_pfn_range_complete(struct vm_area_struct *vma, - unsigned long addr, unsigned long orig_pfn, unsigned long size, - pgprot_t orig_prot) -{ - const unsigned long pfn =3D io_remap_pfn_range_pfn(orig_pfn, size); - const pgprot_t prot =3D pgprot_decrypted(orig_prot); - - return remap_pfn_range_complete(vma, addr, pfn, size, prot); + /* Remap does the actual work. */ + action->type =3D MMAP_REMAP_PFN; + return 0; } =20 #ifdef CONFIG_MMU_NOTIFIER diff --git a/mm/memory.c b/mm/memory.c index 219b9bf6cae0..9dec67a18116 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3099,26 +3099,34 @@ static int do_remap_pfn_range(struct vm_area_struct= *vma, unsigned long addr, } #endif =20 -void remap_pfn_range_prepare(struct vm_area_desc *desc, unsigned long pfn) +int remap_pfn_range_prepare(struct vm_area_desc *desc) { - /* - * We set addr=3DVMA start, end=3DVMA end here, so this won't fail, but we - * check it again on complete and will fail there if specified addr is - * invalid. - */ - get_remap_pgoff(vma_desc_is_cow_mapping(desc), desc->start, desc->end, - desc->start, desc->end, pfn, &desc->pgoff); + const struct mmap_action *action =3D &desc->action; + const unsigned long start =3D action->remap.start; + const unsigned long end =3D start + action->remap.size; + const unsigned long pfn =3D action->remap.start_pfn; + const bool is_cow =3D vma_desc_is_cow_mapping(desc); + int err; + + err =3D get_remap_pgoff(is_cow, start, end, desc->start, desc->end, pfn, + &desc->pgoff); + if (err) + return err; + vma_desc_set_flags_mask(desc, VMA_REMAP_FLAGS); + return 0; } =20 -static int remap_pfn_range_prepare_vma(struct vm_area_struct *vma, unsigne= d long addr, - unsigned long pfn, unsigned long size) +static int remap_pfn_range_prepare_vma(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn, + unsigned long size) { - unsigned long end =3D addr + PAGE_ALIGN(size); + const unsigned long end =3D addr + PAGE_ALIGN(size); + const bool is_cow =3D is_cow_mapping(vma->vm_flags); int err; =20 - err =3D get_remap_pgoff(is_cow_mapping(vma->vm_flags), addr, end, - vma->vm_start, vma->vm_end, pfn, &vma->vm_pgoff); + err =3D get_remap_pgoff(is_cow, addr, end, vma->vm_start, vma->vm_end, + pfn, &vma->vm_pgoff); if (err) return err; =20 @@ -3151,10 +3159,15 @@ int remap_pfn_range(struct vm_area_struct *vma, uns= igned long addr, } EXPORT_SYMBOL(remap_pfn_range); =20 -int remap_pfn_range_complete(struct vm_area_struct *vma, unsigned long add= r, - unsigned long pfn, unsigned long size, pgprot_t prot) +int remap_pfn_range_complete(struct vm_area_struct *vma, + struct mmap_action *action) { - return do_remap_pfn_range(vma, addr, pfn, size, prot); + const unsigned long start =3D action->remap.start; + const unsigned long pfn =3D action->remap.start_pfn; + const unsigned long size =3D action->remap.size; + const pgprot_t prot =3D action->remap.pgprot; + + return do_remap_pfn_range(vma, start, pfn, size, prot); } =20 /** diff --git a/mm/util.c b/mm/util.c index ce7ae80047cf..73c97a748d8e 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1163,43 +1163,6 @@ void flush_dcache_folio(struct folio *folio) EXPORT_SYMBOL(flush_dcache_folio); #endif =20 -/** - * __compat_vma_mmap() - See description for compat_vma_mmap() - * for details. This is the same operation, only with a specific file oper= ations - * struct which may or may not be the same as vma->vm_file->f_op. - * @f_op: The file operations whose .mmap_prepare() hook is specified. - * @file: The file which backs or will back the mapping. - * @vma: The VMA to apply the .mmap_prepare() hook to. - * Returns: 0 on success or error. - */ -int __compat_vma_mmap(const struct file_operations *f_op, - struct file *file, struct vm_area_struct *vma) -{ - struct vm_area_desc desc =3D { - .mm =3D vma->vm_mm, - .file =3D file, - .start =3D vma->vm_start, - .end =3D vma->vm_end, - - .pgoff =3D vma->vm_pgoff, - .vm_file =3D vma->vm_file, - .vma_flags =3D vma->flags, - .page_prot =3D vma->vm_page_prot, - - .action.type =3D MMAP_NOTHING, /* Default */ - }; - int err; - - err =3D f_op->mmap_prepare(&desc); - if (err) - return err; - - mmap_action_prepare(&desc.action, &desc); - set_vma_from_desc(vma, &desc); - return mmap_action_complete(&desc.action, vma); -} -EXPORT_SYMBOL(__compat_vma_mmap); - /** * compat_vma_mmap() - Apply the file's .mmap_prepare() hook to an * existing VMA and execute any requested actions. @@ -1228,7 +1191,31 @@ EXPORT_SYMBOL(__compat_vma_mmap); */ int compat_vma_mmap(struct file *file, struct vm_area_struct *vma) { - return __compat_vma_mmap(file->f_op, file, vma); + struct vm_area_desc desc =3D { + .mm =3D vma->vm_mm, + .file =3D file, + .start =3D vma->vm_start, + .end =3D vma->vm_end, + + .pgoff =3D vma->vm_pgoff, + .vm_file =3D vma->vm_file, + .vma_flags =3D vma->flags, + .page_prot =3D vma->vm_page_prot, + + .action.type =3D MMAP_NOTHING, /* Default */ + }; + int err; + + err =3D vfs_mmap_prepare(file, &desc); + if (err) + return err; + + err =3D mmap_action_prepare(&desc); + if (err) + return err; + + set_vma_from_desc(vma, &desc); + return mmap_action_complete(vma, &desc.action); } EXPORT_SYMBOL(compat_vma_mmap); =20 @@ -1320,8 +1307,8 @@ void snapshot_page(struct page_snapshot *ps, const st= ruct page *page) } } =20 -static int mmap_action_finish(struct mmap_action *action, - const struct vm_area_struct *vma, int err) +static int mmap_action_finish(struct vm_area_struct *vma, + struct mmap_action *action, int err) { /* * If an error occurs, unmap the VMA altogether and return an error. We @@ -1353,37 +1340,38 @@ static int mmap_action_finish(struct mmap_action *a= ction, /** * mmap_action_prepare - Perform preparatory setup for an VMA descriptor * action which need to be performed. - * @desc: The VMA descriptor to prepare for @action. - * @action: The action to perform. + * @desc: The VMA descriptor to prepare for its @desc->action. + * + * Returns: %0 on success, otherwise error. */ -void mmap_action_prepare(struct mmap_action *action, - struct vm_area_desc *desc) +int mmap_action_prepare(struct vm_area_desc *desc) { - switch (action->type) { + switch (desc->action.type) { case MMAP_NOTHING: - break; + return 0; case MMAP_REMAP_PFN: - remap_pfn_range_prepare(desc, action->remap.start_pfn); - break; + return remap_pfn_range_prepare(desc); case MMAP_IO_REMAP_PFN: - io_remap_pfn_range_prepare(desc, action->remap.start_pfn, - action->remap.size); - break; + return io_remap_pfn_range_prepare(desc); } + + WARN_ON_ONCE(1); + return -EINVAL; } EXPORT_SYMBOL(mmap_action_prepare); =20 /** * mmap_action_complete - Execute VMA descriptor action. - * @action: The action to perform. * @vma: The VMA to perform the action upon. + * @action: The action to perform. * * Similar to mmap_action_prepare(). * * Return: 0 on success, or error, at which point the VMA will be unmapped. */ -int mmap_action_complete(struct mmap_action *action, - struct vm_area_struct *vma) +int mmap_action_complete(struct vm_area_struct *vma, + struct mmap_action *action) + { int err =3D 0; =20 @@ -1391,25 +1379,22 @@ int mmap_action_complete(struct mmap_action *action, case MMAP_NOTHING: break; case MMAP_REMAP_PFN: - err =3D remap_pfn_range_complete(vma, action->remap.start, - action->remap.start_pfn, action->remap.size, - action->remap.pgprot); + err =3D remap_pfn_range_complete(vma, action); break; case MMAP_IO_REMAP_PFN: - err =3D io_remap_pfn_range_complete(vma, action->remap.start, - action->remap.start_pfn, action->remap.size, - action->remap.pgprot); + /* Should have been delegated. */ + WARN_ON_ONCE(1); + err =3D -EINVAL; break; } =20 - return mmap_action_finish(action, vma, err); + return mmap_action_finish(vma, action, err); } EXPORT_SYMBOL(mmap_action_complete); #else -void mmap_action_prepare(struct mmap_action *action, - struct vm_area_desc *desc) +int mmap_action_prepare(struct vm_area_desc *desc) { - switch (action->type) { + switch (desc->action.type) { case MMAP_NOTHING: break; case MMAP_REMAP_PFN: @@ -1417,11 +1402,13 @@ void mmap_action_prepare(struct mmap_action *action, WARN_ON_ONCE(1); /* nommu cannot handle these. */ break; } + + return 0; } EXPORT_SYMBOL(mmap_action_prepare); =20 -int mmap_action_complete(struct mmap_action *action, - struct vm_area_struct *vma) +int mmap_action_complete(struct vm_area_struct *vma, + struct mmap_action *action) { int err =3D 0; =20 @@ -1436,7 +1423,7 @@ int mmap_action_complete(struct mmap_action *action, break; } =20 - return mmap_action_finish(action, vma, err); + return mmap_action_finish(vma, action, err); } EXPORT_SYMBOL(mmap_action_complete); #endif diff --git a/mm/vma.c b/mm/vma.c index 8cccaeb8ccbb..ee91f2b76acf 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2641,15 +2641,18 @@ static void __mmap_complete(struct mmap_state *map,= struct vm_area_struct *vma) vma_set_page_prot(vma); } =20 -static void call_action_prepare(struct mmap_state *map, - struct vm_area_desc *desc) +static int call_action_prepare(struct mmap_state *map, + struct vm_area_desc *desc) { - struct mmap_action *action =3D &desc->action; + int err; =20 - mmap_action_prepare(action, desc); + err =3D mmap_action_prepare(desc); + if (err) + return err; =20 - if (action->hide_from_rmap_until_complete) + if (desc->action.hide_from_rmap_until_complete) map->hold_file_rmap_lock =3D true; + return 0; } =20 /* @@ -2673,7 +2676,9 @@ static int call_mmap_prepare(struct mmap_state *map, if (err) return err; =20 - call_action_prepare(map, desc); + err =3D call_action_prepare(map, desc); + if (err) + return err; =20 /* Update fields permitted to be changed. */ map->pgoff =3D desc->pgoff; @@ -2728,13 +2733,12 @@ static bool can_set_ksm_flags_early(struct mmap_sta= te *map) } =20 static int call_action_complete(struct mmap_state *map, - struct vm_area_desc *desc, + struct mmap_action *action, struct vm_area_struct *vma) { - struct mmap_action *action =3D &desc->action; int ret; =20 - ret =3D mmap_action_complete(action, vma); + ret =3D mmap_action_complete(vma, action); =20 /* If we held the file rmap we need to release it. */ if (map->hold_file_rmap_lock) { @@ -2796,7 +2800,7 @@ static unsigned long __mmap_region(struct file *file,= unsigned long addr, __mmap_complete(&map, vma); =20 if (have_mmap_prepare && allocated_new) { - error =3D call_action_complete(&map, &desc, vma); + error =3D call_action_complete(&map, &desc.action, vma); =20 if (error) return error; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index b69eefba4cf7..477a5be65dd2 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -1273,9 +1273,12 @@ static inline int __compat_vma_mmap(const struct fil= e_operations *f_op, if (err) return err; =20 - mmap_action_prepare(&desc.action, &desc); + err =3D mmap_action_prepare(&desc); + if (err) + return err; + set_vma_from_desc(vma, &desc); - return mmap_action_complete(&desc.action, vma); + return mmap_action_complete(vma, &desc.action); } =20 static inline int compat_vma_mmap(struct file *file, diff --git a/tools/testing/vma/include/stubs.h b/tools/testing/vma/include/= stubs.h index 5afb0afe2d48..a30b8bc84955 100644 --- a/tools/testing/vma/include/stubs.h +++ b/tools/testing/vma/include/stubs.h @@ -81,13 +81,13 @@ static inline void free_anon_vma_name(struct vm_area_st= ruct *vma) { } =20 -static inline void mmap_action_prepare(struct mmap_action *action, - struct vm_area_desc *desc) +static inline int mmap_action_prepare(struct vm_area_desc *desc) { + return 0; } =20 -static inline int mmap_action_complete(struct mmap_action *action, - struct vm_area_struct *vma) +static inline int mmap_action_complete(struct vm_area_struct *vma, + struct mmap_action *action) { return 0; } --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B37C396594; Fri, 20 Mar 2026 22:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046412; cv=none; b=MfOIB4nglpdtJ7w34E1OYGFte3+2c+LhLBdwRjLwj61sJPDWnhBUwj1is8U4Drp8kO8eNZZ0gx26WLuRTduYBIsgywKBFZhEQqtbsk16ECkeO/DGbgnQEEVu49XkjGnBjXAPpIoiR2bE19wRIFACDox0pMxKk5nYdrJlsXRJSr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046412; c=relaxed/simple; bh=rSE44385lXGA3oPgZHQ6HYyHSrWEMNs2rXYUR/5mlfY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P2oBktA3kumOz1vpHXvM0TYEwnLt+xoAlWvOYhiTf40BC4+FtjHepqDr/ujXMk9tyPIvCdMcFww3ozxcrc648yKHyMc4xVl9ltNlzXU9PWVzx9HED9O0jAzynQUbUWI97TXXnL3uKwfC5QqJy5Tg3MEui8VKY2H1i8dHltOjztI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BP0JNkME; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BP0JNkME" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63142C4CEF7; Fri, 20 Mar 2026 22:40:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046412; bh=rSE44385lXGA3oPgZHQ6HYyHSrWEMNs2rXYUR/5mlfY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BP0JNkMEU9ScWU1MBWdpsdyiCOPYpMtqHGutZnAF+H9Hw2B/NTyZwP8ZoBjTHaKeD 2sUyw6954caQDGYcilIX5Uh+SUzlPL13IU/boE3byXeL3s+gbquRuTBJwclJInPvKc NH0v05BIyTeUhqynoazNkMeGIrVHEIcKpA5XRR4fvGwsOHM4q6X+IkqPg11Cbh3Vm7 OI9UOBefBD1DiVEwKzychhVbDGAcTugDy0cBTJlfo0Lj+bK0D1n0qTOash8Ie3TDlf an+5lvHTjnqzeymP9HW5N+UAVpq23W2rinElVbNPJveGfcQwgA9vbH+Hx5zvjOao7L 3KSMdtjAvGnCw== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 02/21] mm: add documentation for the mmap_prepare file operation callback Date: Fri, 20 Mar 2026 22:39:28 +0000 Message-ID: <3aebf918c213fa2aecf00a31a444119b5bdd7801.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This documentation makes it easier for a driver/file system implementer to correctly use this callback. It covers the fundamentals, whilst intentionally leaving the less lovely possible actions one might take undocumented (for instance - the success_hook, error_hook fields in mmap_action). The document also covers the new VMA flags implementation which is the only one which will work correctly with mmap_prepare. Acked-by: Vlastimil Babka (SUSE) Signed-off-by: Lorenzo Stoakes (Oracle) --- Documentation/filesystems/index.rst | 1 + Documentation/filesystems/mmap_prepare.rst | 142 +++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 Documentation/filesystems/mmap_prepare.rst diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystem= s/index.rst index f4873197587d..6cbc3e0292ae 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -29,6 +29,7 @@ algorithms work. fiemap files locks + mmap_prepare multigrain-ts mount_api quota diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/fil= esystems/mmap_prepare.rst new file mode 100644 index 000000000000..ae484d371861 --- /dev/null +++ b/Documentation/filesystems/mmap_prepare.rst @@ -0,0 +1,142 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +mmap_prepare callback HOWTO +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +Introduction +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The ``struct file->f_op->mmap()`` callback has been deprecated as it is bo= th a +stability and security risk, and doesn't always permit the merging of adja= cent +mappings resulting in unnecessary memory fragmentation. + +It has been replaced with the ``file->f_op->mmap_prepare()`` callback which +solves these problems. + +This hook is called right at the beginning of setting up the mapping, and +importantly it is invoked *before* any merging of adjacent mappings has ta= ken +place. + +If an error arises upon mapping, it might arise after this callback has be= en +invoked, therefore it should be treated as effectively stateless. + +That is - no resources should be allocated nor state updated to reflect th= at a +mapping has been established, as the mapping may either be merged, or fail= to be +mapped after the callback is complete. + +How To Use +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +In your driver's struct file_operations struct, specify an ``mmap_prepare`` +callback rather than an ``mmap`` one, e.g. for ext4: + +.. code-block:: C + + const struct file_operations ext4_file_operations =3D { + ... + .mmap_prepare =3D ext4_file_mmap_prepare, + }; + +This has a signature of ``int (*mmap_prepare)(struct vm_area_desc *)``. + +Examining the struct vm_area_desc type: + +.. code-block:: C + + struct vm_area_desc { + /* Immutable state. */ + const struct mm_struct *const mm; + struct file *const file; /* May vary from vm_file in stacked calle= rs. */ + unsigned long start; + unsigned long end; + + /* Mutable fields. Populated with initial state. */ + pgoff_t pgoff; + struct file *vm_file; + vma_flags_t vma_flags; + pgprot_t page_prot; + + /* Write-only fields. */ + const struct vm_operations_struct *vm_ops; + void *private_data; + + /* Take further action? */ + struct mmap_action action; + }; + +This is straightforward - you have all the fields you need to set up the +mapping, and you can update the mutable and writable fields, for instance: + +.. code-block:: C + + static int ext4_file_mmap_prepare(struct vm_area_desc *desc) + { + int ret; + struct file *file =3D desc->file; + struct inode *inode =3D file->f_mapping->host; + + ... + + file_accessed(file); + if (IS_DAX(file_inode(file))) { + desc->vm_ops =3D &ext4_dax_vm_ops; + vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT); + } else { + desc->vm_ops =3D &ext4_file_vm_ops; + } + return 0; + } + +Importantly, you no longer have to dance around with reference counts or l= ocks +when updating these fields - **you can simply go ahead and change them**. + +Everything is taken care of by the mapping code. + +VMA Flags +--------- + +Along with ``mmap_prepare``, VMA flags have undergone an overhaul. Where b= efore +you would invoke one of vm_flags_init(), vm_flags_reset(), vm_flags_set(), +vm_flags_clear(), and vm_flags_mod() to modify flags (and to have the +locking done correctly for you, this is no longer necessary. + +Also, the legacy approach of specifying VMA flags via ``VM_READ``, ``VM_WR= ITE``, +etc. - i.e. using a ``-VM_xxx``- macro has changed too. + +When implementing mmap_prepare(), reference flags by their bit number, def= ined +as a ``VMA_xxx_BIT`` macro, e.g. ``VMA_READ_BIT``, ``VMA_WRITE_BIT`` etc., +and use one of (where ``desc`` is a pointer to struct vm_area_desc): + +* ``vma_desc_test_any(desc, ...)`` - Specify a comma-separated list of fla= gs + you wish to test for (whether _any_ are set), e.g. - ``vma_desc_test_any( + desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)`` - returns ``true`` if either ar= e set, + otherwise ``false``. +* ``vma_desc_set_flags(desc, ...)`` - Update the VMA descriptor flags to s= et + additional flags specified by a comma-separated list, + e.g. - ``vma_desc_set_flags(desc, VMA_PFNMAP_BIT, VMA_IO_BIT)``. +* ``vma_desc_clear_flags(desc, ...)`` - Update the VMA descriptor flags to= clear + flags specified by a comma-separated list, e.g. - ``vma_desc_clear_flags( + desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)``. + +Actions +=3D=3D=3D=3D=3D=3D=3D + +You can now very easily have actions be performed upon a mapping once set = up by +utilising simple helper functions invoked upon the struct vm_area_desc +pointer. These are: + +* mmap_action_remap() - Remaps a range consisting only of PFNs for a speci= fic + range starting a virtual address and PFN number of a set size. + +* mmap_action_remap_full() - Same as mmap_action_remap(), only remaps the + entire mapping from ``start_pfn`` onward. + +* mmap_action_ioremap() - Same as mmap_action_remap(), only performs an I/O + remap. + +* mmap_action_ioremap_full() - Same as mmap_action_ioremap(), only remaps + the entire mapping from ``start_pfn`` onward. + +**NOTE:** The ``action`` field should never normally be manipulated direct= ly, +rather you ought to use one of these helpers. --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C9F42E1F11; Fri, 20 Mar 2026 22:40:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046418; cv=none; b=pLDmZ34nai6/H0t/mWL0J0GZwN0xWP77tPi3SCJ5BUns7N9IQ6sl0x9OTi0INcGOXzh1FchRKRvgA+py7UCJi8dzYSZmw+upsuCajq9Slv7O91ilL85tMwKDsACLE8qeTCHMd3Sn1MOvI0h06Y6igGLl51yXN//+E+p8BQyau1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046418; c=relaxed/simple; bh=KGyUqER+1KMemEPNwb05yxF1iWQpDSjowRQtc3QKLCs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y+j+ODVkTHoLImKjicwe4NsFYhk6tzKGA5nAz+hQn1ph2JgwNyC4sEosYwVdxL5UeW5M7+nwXqu6k6kDoMyW2rP5T50WUPOec3XvDA7R6kuYrly4ZhDjmY842vliZLsQuGivsBJNBoUokTlaVc7nzHIYZy8JuRXFhYCx/eZ19O4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dA9XZnpB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dA9XZnpB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40016C2BC87; Fri, 20 Mar 2026 22:40:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046414; bh=KGyUqER+1KMemEPNwb05yxF1iWQpDSjowRQtc3QKLCs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dA9XZnpBcEJcM42a6vjSFyPET/ma7T86PWJqOQGw7Jyg+kRd+83nlRoqc0O7v96SK YvRsSOeFduElA2i9LlLPBrveszNKsV/wEHNPDsjTRuTRE3cLy3G5NskTN8/H53cVFn 3Ywq6aUqH5SvMgIF0ep7yj4Snw0UswftBXcYfPQrdKctrim6TYzDgn/Qtd4p5XDqAn ksYAYdoClblLQQ4HNNMt+rmiwkQjH309dGenzWTjBN0noIg1HDWbSeRrCCp0QY7i1+ Q3/R3MYNQe23Nn9QayxJ05lxx2gjnsKg3UDM1l+cacq1VVEFTuAkz0zBxU0O822v1t h+KOY6lq/0WEQ== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 03/21] mm: document vm_operations_struct->open the same as close() Date: Fri, 20 Mar 2026 22:39:29 +0000 Message-ID: <7d0ca833c12014320f0fa00f816f95e6e10076f2.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Describe when the operation is invoked and the context in which it is invoked, matching the description already added for vm_op->close(). While we're here, update all outdated references to an 'area' field for VMAs to the more consistent 'vma'. Acked-by: Vlastimil Babka (SUSE) Signed-off-by: Lorenzo Stoakes (Oracle) --- include/linux/mm.h | 15 ++++++++++----- tools/testing/vma/include/dup.h | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 1e63b3a44a47..da94edb287cd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -766,15 +766,20 @@ struct vm_uffd_ops; * to the functions called when a no-page or a wp-page exception occurs. */ struct vm_operations_struct { - void (*open)(struct vm_area_struct * area); + /** + * @open: Called when a VMA is remapped, split or forked. Not called + * upon first mapping a VMA. + * Context: User context. May sleep. Caller holds mmap_lock. + */ + void (*open)(struct vm_area_struct *vma); /** * @close: Called when the VMA is being removed from the MM. * Context: User context. May sleep. Caller holds mmap_lock. */ - void (*close)(struct vm_area_struct * area); + void (*close)(struct vm_area_struct *vma); /* Called any time before splitting to check if it's allowed */ - int (*may_split)(struct vm_area_struct *area, unsigned long addr); - int (*mremap)(struct vm_area_struct *area); + int (*may_split)(struct vm_area_struct *vma, unsigned long addr); + int (*mremap)(struct vm_area_struct *vma); /* * Called by mprotect() to make driver-specific permission * checks before mprotect() is finalised. The VMA must not @@ -786,7 +791,7 @@ struct vm_operations_struct { vm_fault_t (*huge_fault)(struct vm_fault *vmf, unsigned int order); vm_fault_t (*map_pages)(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); - unsigned long (*pagesize)(struct vm_area_struct * area); + unsigned long (*pagesize)(struct vm_area_struct *vma); =20 /* notification that a previously read-only page is about to become * writable, if an error is returned it will cause a SIGBUS */ diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 477a5be65dd2..26c6c3255a94 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -632,15 +632,20 @@ struct vm_area_struct { } __randomize_layout; =20 struct vm_operations_struct { - void (*open)(struct vm_area_struct * area); + /** + * @open: Called when a VMA is remapped, split or forked. Not called + * upon first mapping a VMA. + * Context: User context. May sleep. Caller holds mmap_lock. + */ + void (*open)(struct vm_area_struct *vma); /** * @close: Called when the VMA is being removed from the MM. * Context: User context. May sleep. Caller holds mmap_lock. */ - void (*close)(struct vm_area_struct * area); + void (*close)(struct vm_area_struct *vma); /* Called any time before splitting to check if it's allowed */ - int (*may_split)(struct vm_area_struct *area, unsigned long addr); - int (*mremap)(struct vm_area_struct *area); + int (*may_split)(struct vm_area_struct *vma, unsigned long addr); + int (*mremap)(struct vm_area_struct *vma); /* * Called by mprotect() to make driver-specific permission * checks before mprotect() is finalised. The VMA must not @@ -652,7 +657,7 @@ struct vm_operations_struct { vm_fault_t (*huge_fault)(struct vm_fault *vmf, unsigned int order); vm_fault_t (*map_pages)(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff); - unsigned long (*pagesize)(struct vm_area_struct * area); + unsigned long (*pagesize)(struct vm_area_struct *vma); =20 /* notification that a previously read-only page is about to become * writable, if an error is returned it will cause a SIGBUS */ --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23C6238BF6C; Fri, 20 Mar 2026 22:40:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046418; cv=none; b=DC6ZkBjK8Yl9U5+fkJI9uf0NjVgzfRB8sWzh8zGl43rhDCHNYGbAey6QCjQcuuvJhn0ShaOJ9o5rlDFxkqMUKBWLSw/nWlAbIkEtRI9Ad6NsuNOaO8wKXApfbarhE+7bRoGHj2N1pfJ/NhEyXnnqDVYkXb9Z24htQbgFe1QCAps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046418; c=relaxed/simple; bh=L0GQ2G+rRvGPAFrt5sDMa8oj/FKKHLhal+DfkgK7NEA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q4UD/HTt4TIh7KhDU2iUKNkDDK6SOvZHowHZIhcBkyM1BamNT+V5RaMiRJyXxoXgaL+jkOUTNd3BB0Pui5NiyraFWiF8r4WahdAxUNrV1fk7X3/CQJKOAQ+uuW2R/HvXvx8RRqfZltl3ixS5mcNOtKS0iiJGtp0UPsJh1cYLoDE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bFVvmSaq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bFVvmSaq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32A85C2BC9E; Fri, 20 Mar 2026 22:40:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046417; bh=L0GQ2G+rRvGPAFrt5sDMa8oj/FKKHLhal+DfkgK7NEA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bFVvmSaqDqJLoDlg+6noI1Wxcf1pqHJkBZjp3o48gNpg4DH44rSaBGPbLYz/qYZkM Nd8QwUFV1MaXSsj8jMMIjACmWtdO9Y/w9/2x+JJoanOvv9XyP9qFBdKZZkxb1A4iHC tkLQhKpN3alMVayVyEb9I/udX19c+sGN7XDtcaIOMLn6nekaglVJYw11nFmLwGrBc4 hsCpEv1VvOJUhXrUrciA2il+pJ/sMHTGafOaYgDrjovh6SCT8n/MXsfdX3tgBGQOS2 ldB6CM957Gunm1xRN2e3elhZJR5PM4eGqJVCx4WeRxsCBdQ44ZurTnPnt2jh0taBlN sszGTQBOqqiOA== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 04/21] mm: avoid deadlock when holding rmap on mmap_prepare error Date: Fri, 20 Mar 2026 22:39:30 +0000 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit ac0a3fc9c07d ("mm: add ability to take further action in vm_area_desc") added the ability for drivers to instruct mm to take actions after the .mmap_prepare callback is complete. To make life simpler and safer, this is done before the VMA/mmap write lock is dropped but when the VMA is completely established. So on error, we simply munmap() the VMA. As part of this implementation, unfortunately a horrible hack had to be implemented to support some questionable behaviour hugetlb relies upon - that is that the file rmap lock is held until the operation is complete. The implementation, for convenience, did this in mmap_action_finish() so both the VMA and mmap_prepare compatibility layer paths would have this correctly handled. However, it turns out there is a mistake here - the rmap lock cannot be held on munmap, as free_pgtables() -> unlink_file_vma_batch_add() -> unlink_file_vma_batch_process() takes the file rmap lock. We therefore currently have a deadlock issue that might arise. Resolve this by leaving it to callers to handle the unmap. The compatibility layer does not support this rmap behaviour, so we simply have it unmap on error after calling mmap_action_complete(). In the VMA implementation, we only perform the unmap after the rmap lock is dropped. This resolves the issue by ensuring the rmap lock is always dropped when the unmap occurs. Fixes: ac0a3fc9c07d ("mm: add ability to take further action in vm_area_des= c") Cc: Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- mm/util.c | 12 +++++++----- mm/vma.c | 13 ++++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/mm/util.c b/mm/util.c index 73c97a748d8e..a2cfa0d77c35 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1215,7 +1215,13 @@ int compat_vma_mmap(struct file *file, struct vm_are= a_struct *vma) return err; =20 set_vma_from_desc(vma, &desc); - return mmap_action_complete(vma, &desc.action); + err =3D mmap_action_complete(vma, &desc.action); + if (err) { + const size_t len =3D vma_pages(vma) << PAGE_SHIFT; + + do_munmap(current->mm, vma->vm_start, len, NULL); + } + return err; } EXPORT_SYMBOL(compat_vma_mmap); =20 @@ -1316,10 +1322,6 @@ static int mmap_action_finish(struct vm_area_struct = *vma, * invoked if we do NOT merge, so we only clean up the VMA we created. */ if (err) { - const size_t len =3D vma_pages(vma) << PAGE_SHIFT; - - do_munmap(current->mm, vma->vm_start, len, NULL); - if (action->error_hook) { /* We may want to filter the error. */ err =3D action->error_hook(err); diff --git a/mm/vma.c b/mm/vma.c index ee91f2b76acf..3fc5fe4f1a7c 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2736,9 +2736,9 @@ static int call_action_complete(struct mmap_state *ma= p, struct mmap_action *action, struct vm_area_struct *vma) { - int ret; + int err; =20 - ret =3D mmap_action_complete(vma, action); + err =3D mmap_action_complete(vma, action); =20 /* If we held the file rmap we need to release it. */ if (map->hold_file_rmap_lock) { @@ -2746,7 +2746,14 @@ static int call_action_complete(struct mmap_state *m= ap, =20 i_mmap_unlock_write(file->f_mapping); } - return ret; + + if (err) { + const size_t len =3D vma_pages(vma) << PAGE_SHIFT; + + do_munmap(current->mm, vma->vm_start, len, NULL); + } + + return err; } =20 static unsigned long __mmap_region(struct file *file, unsigned long addr, --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFF2E3BA255; Fri, 20 Mar 2026 22:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046420; cv=none; b=exxX6GfERkSI0AR0g3QZWOVK40BpFsRaag6pFMdcRTPmrSKDfZSIaFbTw522jh1GrDI9dOl5DqEfJRIBxrkYxU4JEf0V9VPleMfCb3jszYf1VVOURq7CK3Y3UoTDrY1akifo3eDSw0USKYIakz+Dvvtmb/hJvfaVHlq8wE6NuFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046420; c=relaxed/simple; bh=nTMi7MwgWhsqzEL3innRO8x3UGd+wS99PKV5J1/IH6A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i3sxqqVN0YYD87i8AvNw1QSii3URvjKjPxa4qHCCqSOmhs8twgu0N0owU+x4yp3LTOx/9gfD7hj58rr/0i/YkAo+0TqlciO9pCsDCb4WCUDm9BuQ2cCM31o+WnbQ32QzpFoIEUasebvSa/R+0PM2fJ4S7kBr78QRXaEhH0Jzm4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gjT5OfG/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gjT5OfG/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 04E63C2BCB0; Fri, 20 Mar 2026 22:40:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046420; bh=nTMi7MwgWhsqzEL3innRO8x3UGd+wS99PKV5J1/IH6A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gjT5OfG/LeaNBmLBTUcJPgnFfktEPzYQp1DS+lVjzFF9mviCzUaOB/pv5EHU0EsMM 0WimX7637MvnHvbDM5ijVu4+dtO8s0Vvfj0NenkAY/HaB3Ad88bN2u1mlJ0c1QIkvA cIxW5OOMSphnCBkiQSwasBNYmIRGz9qUDAFkFdd6pzQVCWVUiupz5jZCRHZs5XTkYp DB/EkEvfD1Afqqzo+MwllMaR4ktnrqaRLNCUlkajLtTYHG7nILemLEO/ih0qWLXHHT sHtHoecxEP3lZPCejF3YNgU1Tz5BXICj27Ua1a6alZHwlWd+3T5ga9RjPT/WeFhCgB Wbo/bkpNIqoog== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 05/21] mm: switch the rmap lock held option off in compat layer Date: Fri, 20 Mar 2026 22:39:31 +0000 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In the mmap_prepare compatibility layer, we don't need to hold the rmap lock, as we are being called from an .mmap handler. The .mmap_prepare hook, when invoked in the VMA logic, is called prior to the VMA being instantiated, but the completion hook is called after the VMA is linked into the maple tree, meaning rmap walkers can reach it. The mmap hook does not link the VMA into the tree, so this cannot happen. Therefore it's safe to simply disable this in the mmap_prepare compatibility layer. Also update VMA tests code to reflect current compatibility layer state. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- mm/util.c | 6 ++++- tools/testing/vma/include/dup.h | 42 +++++++++++++++++---------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/mm/util.c b/mm/util.c index a2cfa0d77c35..182f0f5cc400 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1204,6 +1204,7 @@ int compat_vma_mmap(struct file *file, struct vm_area= _struct *vma) .action.type =3D MMAP_NOTHING, /* Default */ }; + struct mmap_action *action =3D &desc.action; int err; err =3D vfs_mmap_prepare(file, &desc); @@ -1214,8 +1215,11 @@ int compat_vma_mmap(struct file *file, struct vm_are= a_struct *vma) if (err) return err; + /* being invoked from .mmmap means we don't have to enforce this. */ + action->hide_from_rmap_until_complete =3D false; + set_vma_from_desc(vma, &desc); - err =3D mmap_action_complete(vma, &desc.action); + err =3D mmap_action_complete(vma, action); if (err) { const size_t len =3D vma_pages(vma) << PAGE_SHIFT; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 26c6c3255a94..c62d3998e922 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -1256,8 +1256,17 @@ static inline void vma_set_anonymous(struct vm_area_= struct *vma) static inline void set_vma_from_desc(struct vm_area_struct *vma, struct vm_area_desc *desc); -static inline int __compat_vma_mmap(const struct file_operations *f_op, - struct file *file, struct vm_area_struct *vma) +static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc = *desc) +{ + return file->f_op->mmap_prepare(desc); +} + +static inline unsigned long vma_pages(struct vm_area_struct *vma) +{ + return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +} + +static inline int compat_vma_mmap(struct file *file, struct vm_area_struct= *vma) { struct vm_area_desc desc =3D { .mm =3D vma->vm_mm, @@ -1272,9 +1281,10 @@ static inline int __compat_vma_mmap(const struct fil= e_operations *f_op, .action.type =3D MMAP_NOTHING, /* Default */ }; + struct mmap_action *action =3D &desc.action; int err; - err =3D f_op->mmap_prepare(&desc); + err =3D vfs_mmap_prepare(file, &desc); if (err) return err; @@ -1282,28 +1292,25 @@ static inline int __compat_vma_mmap(const struct fi= le_operations *f_op, if (err) return err; + /* being invoked from .mmmap means we don't have to enforce this. */ + action->hide_from_rmap_until_complete =3D false; + set_vma_from_desc(vma, &desc); - return mmap_action_complete(vma, &desc.action); -} + err =3D mmap_action_complete(vma, action); + if (err) { + const size_t len =3D vma_pages(vma) << PAGE_SHIFT; -static inline int compat_vma_mmap(struct file *file, - struct vm_area_struct *vma) -{ - return __compat_vma_mmap(file->f_op, file, vma); + do_munmap(current->mm, vma->vm_start, len, NULL); + } + return err; } - static inline void vma_iter_init(struct vma_iterator *vmi, struct mm_struct *mm, unsigned long addr) { mas_init(&vmi->mas, &mm->mm_mt, addr); } -static inline unsigned long vma_pages(struct vm_area_struct *vma) -{ - return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; -} - static inline void mmap_assert_locked(struct mm_struct *); static inline struct vm_area_struct *find_vma_intersection(struct mm_struc= t *mm, unsigned long start_addr, @@ -1473,11 +1480,6 @@ static inline int vfs_mmap(struct file *file, struct= vm_area_struct *vma) return file->f_op->mmap(file, vma); } -static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc = *desc) -{ - return file->f_op->mmap_prepare(desc); -} - static inline void vma_set_file(struct vm_area_struct *vma, struct file *f= ile) { /* Changing an anonymous vma with this is illegal */ -- 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 06E2037B008; Fri, 20 Mar 2026 22:40:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046426; cv=none; b=ANwP8rHIWelxD/JxGS2uAUxjmcD7dpo0EMdyso8RE2YMJ16QLIiqDQm53agB+SiKt7p80S6hN+XHUyivj7eoV3DUsPTEM4U2VTTkp6RmPXelHMCI0xGJcmmJb32OI3z92ulTWSX8KP4r+kTH2ZUYT5wCU09Ip9Xm+K9Mkkqq3k4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046426; c=relaxed/simple; bh=5B0UudB5t6IvoUSjas4gSsitxv5wljP/xv5/LMRSwMw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=njpI+uR4fdBuKZ1m4+twCRk7NFA76GfSSmGV12zh6njZ7MZhB8uMrkqlPJAEqCO0pdrfv/UeU/zhzRzyu4GXxQukX2Muo6KAEziTe+L5HWgAyvMxeVrWrRrids9hpGJEYFZygGyxDR4vt4/DYq20vvaV9c6klhkZ5bYwovcRVHo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KUQ4yJnN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KUQ4yJnN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BDF76C2BCB0; Fri, 20 Mar 2026 22:40:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046423; bh=5B0UudB5t6IvoUSjas4gSsitxv5wljP/xv5/LMRSwMw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KUQ4yJnN/WuHnEHkwKNXjPL29+3niu71Tepf6T8MO4WkDdogsFLE72V8PeJFDVlF4 Bgq2IUCnGX2DqjqxgG9VU/AJ9tvaRvZoXCJ/edOpA2ecyHNMPx/827tzdtxUxlno1b kB/jx2f29BxgqysOfNJm2thngFQSBiZldAHGABhZEbYYZtllNjGAzqunIUk7syMpWE q4F2EYNQ3xjEpxq+z70oW/TZyTdZnIe3eNlH70hr0fh7kvql3+XaNSIzX6J9joDX/J Wo7adkEJHy2wBoh1A0sfY4bHYjqE6KjPrlgSkBE1+cXFhZzg9cVq3BIUNXtQCYbYf7 VMR8sVXp9E6aw== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 06/21] mm/vma: remove superfluous map->hold_file_rmap_lock Date: Fri, 20 Mar 2026 22:39:32 +0000 Message-ID: <42c3fbb701e361a17193ecda0d2dabcc326288a5.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We don't need to reference this field, it's confusing as it duplicates mmap_action->hide_from_rmap_until_complete, so thread the mmap_action through to __mmap_new_vma() instead and use the same field consistently. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- mm/vma.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/mm/vma.c b/mm/vma.c index 3fc5fe4f1a7c..6105f54cea61 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -38,8 +38,6 @@ struct mmap_state { =20 /* Determine if we can check KSM flags early in mmap() logic. */ bool check_ksm_early :1; - /* If we map new, hold the file rmap lock on mapping. */ - bool hold_file_rmap_lock :1; /* If .mmap_prepare changed the file, we don't need to pin. */ bool file_doesnt_need_get :1; }; @@ -2531,10 +2529,12 @@ static int __mmap_new_file_vma(struct mmap_state *m= ap, * * @map: Mapping state. * @vmap: Output pointer for the new VMA. + * @action: Any mmap_prepare action that is still to complete. * * Returns: Zero on success, or an error. */ -static int __mmap_new_vma(struct mmap_state *map, struct vm_area_struct **= vmap) +static int __mmap_new_vma(struct mmap_state *map, struct vm_area_struct **= vmap, + struct mmap_action *action) { struct vma_iterator *vmi =3D map->vmi; int error =3D 0; @@ -2583,7 +2583,7 @@ static int __mmap_new_vma(struct mmap_state *map, str= uct vm_area_struct **vmap) vma_start_write(vma); vma_iter_store_new(vmi, vma); map->mm->map_count++; - vma_link_file(vma, map->hold_file_rmap_lock); + vma_link_file(vma, action->hide_from_rmap_until_complete); =20 /* * vma_merge_new_range() calls khugepaged_enter_vma() too, the below @@ -2650,8 +2650,6 @@ static int call_action_prepare(struct mmap_state *map, if (err) return err; =20 - if (desc->action.hide_from_rmap_until_complete) - map->hold_file_rmap_lock =3D true; return 0; } =20 @@ -2741,7 +2739,7 @@ static int call_action_complete(struct mmap_state *ma= p, err =3D mmap_action_complete(vma, action); =20 /* If we held the file rmap we need to release it. */ - if (map->hold_file_rmap_lock) { + if (action->hide_from_rmap_until_complete) { struct file *file =3D vma->vm_file; =20 i_mmap_unlock_write(file->f_mapping); @@ -2795,7 +2793,7 @@ static unsigned long __mmap_region(struct file *file,= unsigned long addr, =20 /* ...but if we can't, allocate a new VMA. */ if (!vma) { - error =3D __mmap_new_vma(&map, &vma); + error =3D __mmap_new_vma(&map, &vma, &desc.action); if (error) goto unacct_error; allocated_new =3D true; --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B5CF53CCA1F; Fri, 20 Mar 2026 22:40:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046428; cv=none; b=TGObkgFLVZJ3idtudswZff6goKU05fw4V/VrqekBVRmvzRnVcOqrNruRGedNlEuHRH9EKDZcHhPjkg40s/d3dc+h7nwJkeGCMr4b/i8rcltxpGStXu0m8TJZAihINtSHIr2aigxEb5nlp45ZYAi15Rc49t4yYtvNJ5uJFA/Ia7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046428; c=relaxed/simple; bh=R1lkxijSil+wWCmTaCAVOrSSJhw850u2PwIZedjzsl0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jCuLADUfIWLLJ5OJOmN3bArF2SwVMIuwODsCaO2DimEpBJ7N0I3VTeuBV/HN70npcO5dix8jmu01ep3y4IlkNhfLWrk0b9Cmu66At35DFxPiVse981yY+xNZQfhP3ag3Ag5iw6BzQ6EjwNuTRuvjGtFvHkFCM6FdvH44R6ur3J4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i6DKCirE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="i6DKCirE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C47DEC4CEF7; Fri, 20 Mar 2026 22:40:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046426; bh=R1lkxijSil+wWCmTaCAVOrSSJhw850u2PwIZedjzsl0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i6DKCirEGA6ZKizhrliF1gHxi+wwd3A8ZZ9TJ46wWZGYGTuYJQEieZIrCaNLV0Ceu qrZEFXJM4/VLRUccl/77xdjQ4wRRVkIdtBV+/nu2XvIoRVT8p7pCJLAAVYVeU8/Hzo va/np2+Epr0pid/tAuswDsibpsHEi12de1oz2RUJQlsYB7UdRpwpZlijugUuLtLxrv 4x7AWSkBBb4HU+OspbVpMSRtPEJqebIKPtfhisYBdi1CvX+Dm4VvpDRVFl6BpL4tmf qUfrr4IQZoCv3oOucELvpWRO6oesrCrqDegzslK5EFUCjaXz8mFoxvNVfwFeU6XHxl tyaQV5/aT+25w== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 07/21] mm: have mmap_action_complete() handle the rmap lock and unmap Date: Fri, 20 Mar 2026 22:39:33 +0000 Message-ID: <8d1ee8ebd3542d006a47e8382fb80cf5b57ecf10.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rather than have the callers handle this both the rmap lock release and unmapping the VMA on error, handle it within the mmap_action_complete() logic where it makes sense to, being careful not to unlock twice. This simplifies the logic and makes it harder to make mistake with this, while retaining correct behaviour with regard to avoiding deadlocks. Also replace the call_action_complete() function with a direct invocation of mmap_action_complete() as the abstraction is no longer required. Also update the VMA tests to reflect this change. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- mm/internal.h | 19 +++++++++++++++ mm/util.c | 41 +++++++++++++++------------------ mm/vma.c | 26 +-------------------- tools/testing/vma/include/dup.h | 8 +------ 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index 0256ca44115a..760fbff9c430 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1817,6 +1817,25 @@ static inline int io_remap_pfn_range_prepare(struct = vm_area_desc *desc) return 0; } +/* + * When we succeed an mmap action or just before we unmap a VMA on error, = we + * need to ensure any rmap lock held is released. On unmap it's required to + * avoid a deadlock. + */ +static inline void maybe_rmap_unlock_action(struct vm_area_struct *vma, + struct mmap_action *action) +{ + struct file *file; + + if (!action->hide_from_rmap_until_complete) + return; + + VM_WARN_ON_ONCE(vma_is_anonymous(vma)); + file =3D vma->vm_file; + i_mmap_unlock_write(file->f_mapping); + action->hide_from_rmap_until_complete =3D false; +} + #ifdef CONFIG_MMU_NOTIFIER static inline int clear_flush_young_ptes_notify(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, unsigned int nr) diff --git a/mm/util.c b/mm/util.c index 182f0f5cc400..a187f3ab4437 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1219,13 +1219,7 @@ int compat_vma_mmap(struct file *file, struct vm_are= a_struct *vma) action->hide_from_rmap_until_complete =3D false; set_vma_from_desc(vma, &desc); - err =3D mmap_action_complete(vma, action); - if (err) { - const size_t len =3D vma_pages(vma) << PAGE_SHIFT; - - do_munmap(current->mm, vma->vm_start, len, NULL); - } - return err; + return mmap_action_complete(vma, action); } EXPORT_SYMBOL(compat_vma_mmap); @@ -1320,26 +1314,30 @@ void snapshot_page(struct page_snapshot *ps, const = struct page *page) static int mmap_action_finish(struct vm_area_struct *vma, struct mmap_action *action, int err) { + size_t len; + + if (!err && action->success_hook) + err =3D action->success_hook(vma); + + /* do_munmap() might take rmap lock, so release if held. */ + maybe_rmap_unlock_action(vma, action); + if (!err) + return 0; + /* * If an error occurs, unmap the VMA altogether and return an error. We * only clear the newly allocated VMA, since this function is only * invoked if we do NOT merge, so we only clean up the VMA we created. */ - if (err) { - if (action->error_hook) { - /* We may want to filter the error. */ - err =3D action->error_hook(err); - - /* The caller should not clear the error. */ - VM_WARN_ON_ONCE(!err); - } - return err; + len =3D vma_pages(vma) << PAGE_SHIFT; + do_munmap(current->mm, vma->vm_start, len, NULL); + if (action->error_hook) { + /* We may want to filter the error. */ + err =3D action->error_hook(err); + /* The caller should not clear the error. */ + VM_WARN_ON_ONCE(!err); } - - if (action->success_hook) - return action->success_hook(vma); - - return 0; + return err; } #ifdef CONFIG_MMU @@ -1377,7 +1375,6 @@ EXPORT_SYMBOL(mmap_action_prepare); */ int mmap_action_complete(struct vm_area_struct *vma, struct mmap_action *action) - { int err =3D 0; diff --git a/mm/vma.c b/mm/vma.c index 6105f54cea61..86f947c90442 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2730,30 +2730,6 @@ static bool can_set_ksm_flags_early(struct mmap_stat= e *map) return false; } -static int call_action_complete(struct mmap_state *map, - struct mmap_action *action, - struct vm_area_struct *vma) -{ - int err; - - err =3D mmap_action_complete(vma, action); - - /* If we held the file rmap we need to release it. */ - if (action->hide_from_rmap_until_complete) { - struct file *file =3D vma->vm_file; - - i_mmap_unlock_write(file->f_mapping); - } - - if (err) { - const size_t len =3D vma_pages(vma) << PAGE_SHIFT; - - do_munmap(current->mm, vma->vm_start, len, NULL); - } - - return err; -} - static unsigned long __mmap_region(struct file *file, unsigned long addr, unsigned long len, vma_flags_t vma_flags, unsigned long pgoff, struct list_head *uf) @@ -2805,7 +2781,7 @@ static unsigned long __mmap_region(struct file *file,= unsigned long addr, __mmap_complete(&map, vma); if (have_mmap_prepare && allocated_new) { - error =3D call_action_complete(&map, &desc.action, vma); + error =3D mmap_action_complete(vma, &desc.action); if (error) return error; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index c62d3998e922..bf8cffe1ea58 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -1296,13 +1296,7 @@ static inline int compat_vma_mmap(struct file *file,= struct vm_area_struct *vma) action->hide_from_rmap_until_complete =3D false; set_vma_from_desc(vma, &desc); - err =3D mmap_action_complete(vma, action); - if (err) { - const size_t len =3D vma_pages(vma) << PAGE_SHIFT; - - do_munmap(current->mm, vma->vm_start, len, NULL); - } - return err; + return mmap_action_complete(vma, action); } static inline void vma_iter_init(struct vma_iterator *vmi, -- 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 87F3B3CE481; Fri, 20 Mar 2026 22:40:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046431; cv=none; b=TaQdMTxBlG5W2m47siqLolKMMpg2PkdgkrhEnRX5lwwqOApogfkrnkKJntGK/Z8srH/N4GGvvLrnSvNECwruXtxR5OPq5mOgkgfC2fvHtmSFh9Ewlh37q/Wk2GeJkxpJTeyzsN/qjfYhhPcKkrn4M0dDsa5KgPhHhJNqJgPyHVQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046431; c=relaxed/simple; bh=qAhfMos8IwFooxBjEFHUxTCuNkdrDVKu5O5kx2DPVmE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cZu31Yup9ioHJpJvOIsNMUgraMrq2bnvhj425Scy2ZZqX1tpMQLT+uROuAGEt6HaqnHzn7/g0I0nHzlBv3t+tacCfVedJ1vHh65VvJCs0+XmleE/dRnLHnoPavD6rwj/67XEm8/JYbu21BkLHtU2dkxAVUqic+ex+ure5N3YCVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TLisp+hv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TLisp+hv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 88F6BC2BC87; Fri, 20 Mar 2026 22:40:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046429; bh=qAhfMos8IwFooxBjEFHUxTCuNkdrDVKu5O5kx2DPVmE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TLisp+hv4ow09LB9AVlXKuMhwRKSSKuNEpFuAKH0Q7Ihro9jWw8Eh23H+jcy8zoIX LTidWRL9ALKO7Kiqr25TAWzAyaWrR41GHIOGj2CjjPROLpiv7TyZNMW2wSVrGR93wq Z1libGyblqUmK4pVfU6QSz+wSnOqWmUAOn3Z25KxC8a29jMs3jBVpQeI2awvI+aQwB coj+MtOjo0bAokvhqSHMZ9iPlPPPJQ56r3OQXKPbv9koVAiApSi+Fx8OvPuE8H+XN5 IgwzEn04XCpE3Dy8vhxD39PO44ZXVqOBGxxDhgjxD9vCJMVNNS8wvf7LPTEMe1XMZn nRx99TzqAolCg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 08/21] mm: add vm_ops->mapped hook Date: Fri, 20 Mar 2026 22:39:34 +0000 Message-ID: <4c5e98297eb0aae9565c564e1c296a112702f144.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Previously, when a driver needed to do something like establish a reference count, it could do so in the mmap hook in the knowledge that the mapping would succeed. With the introduction of f_op->mmap_prepare this is no longer the case, as it is invoked prior to actually establishing the mapping. mmap_prepare is not appropriate for this kind of thing as it is called before any merge might take place, and after which an error might occur meaning resources could be leaked. To take this into account, introduce a new vm_ops->mapped callback which is invoked when the VMA is first mapped (though notably - not when it is merged - which is correct and mirrors existing mmap/open/close behaviour). We do better that vm_ops->open() here, as this callback can return an error, at which point the VMA will be unmapped. Note that vm_ops->mapped() is invoked after any mmap action is complete (such as I/O remapping). We intentionally do not expose the VMA at this point, exposing only the fields that could be used, and an output parameter in case the operation needs to update the vma->vm_private_data field. In order to deal with stacked filesystems which invoke inner filesystem's mmap() invocations, add __compat_vma_mapped() and invoke it on vfs_mmap() (via compat_vma_mmap()) to ensure that the mapped callback is handled when an mmap() caller invokes a nested filesystem's mmap_prepare() callback. Update the mmap_prepare documentation to describe the mapped hook and make it clear what its intended use is. The vm_ops->mapped() call is handled by the mmap complete logic to ensure the same code paths are handled by both the compatibility and VMA layers. Additionally, update VMA userland test headers to reflect the change. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- Documentation/filesystems/mmap_prepare.rst | 15 ++++ include/linux/fs.h | 9 ++- include/linux/mm.h | 17 ++++ mm/util.c | 90 +++++++++++++++------- mm/vma.c | 1 - tools/testing/vma/include/dup.h | 17 ++++ 6 files changed, 120 insertions(+), 29 deletions(-) diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/fil= esystems/mmap_prepare.rst index ae484d371861..f14b35ee11d5 100644 --- a/Documentation/filesystems/mmap_prepare.rst +++ b/Documentation/filesystems/mmap_prepare.rst @@ -25,6 +25,21 @@ That is - no resources should be allocated nor state upd= ated to reflect that a mapping has been established, as the mapping may either be merged, or fail= to be mapped after the callback is complete. =20 +Mapped callback +--------------- + +If resources need to be allocated per-mapping, or state such as a reference +count needs to be manipulated, this should be done using the ``vm_ops->map= ped`` +hook, which itself should be set by the >mmap_prepare hook. + +This callback is only invoked if a new mapping has been established and wa= s not +merged with any other, and is invoked at a point where no error may occur = before +the mapping is established. + +You may return an error to the callback itself, which will cause the mappi= ng to +become unmapped and an error returned to the mmap() caller. This is useful= if +resources need to be allocated, and that allocation might fail. + How To Use =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/include/linux/fs.h b/include/linux/fs.h index a2628a12bd2b..c390f5c667e3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2059,13 +2059,20 @@ static inline bool can_mmap_file(struct file *file) } =20 int compat_vma_mmap(struct file *file, struct vm_area_struct *vma); +int __vma_check_mmap_hook(struct vm_area_struct *vma); =20 static inline int vfs_mmap(struct file *file, struct vm_area_struct *vma) { + int err; + if (file->f_op->mmap_prepare) return compat_vma_mmap(file, vma); =20 - return file->f_op->mmap(file, vma); + err =3D file->f_op->mmap(file, vma); + if (err) + return err; + + return __vma_check_mmap_hook(vma); } =20 static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc = *desc) diff --git a/include/linux/mm.h b/include/linux/mm.h index da94edb287cd..ad1b8c3c0cfd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -777,6 +777,23 @@ struct vm_operations_struct { * Context: User context. May sleep. Caller holds mmap_lock. */ void (*close)(struct vm_area_struct *vma); + /** + * @mapped: Called when the VMA is first mapped in the MM. Not called if + * the new VMA is merged with an adjacent VMA. + * + * The @vm_private_data field is an output field allowing the user to + * modify vma->vm_private_data as necessary. + * + * ONLY valid if set from f_op->mmap_prepare. Will result in an error if + * set from f_op->mmap. + * + * Returns %0 on success, or an error otherwise. On error, the VMA will + * be unmapped. + * + * Context: User context. May sleep. Caller holds mmap_lock. + */ + int (*mapped)(unsigned long start, unsigned long end, pgoff_t pgoff, + const struct file *file, void **vm_private_data); /* Called any time before splitting to check if it's allowed */ int (*may_split)(struct vm_area_struct *vma, unsigned long addr); int (*mremap)(struct vm_area_struct *vma); diff --git a/mm/util.c b/mm/util.c index a187f3ab4437..df95ae41e09b 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1163,33 +1163,7 @@ void flush_dcache_folio(struct folio *folio) EXPORT_SYMBOL(flush_dcache_folio); #endif =20 -/** - * compat_vma_mmap() - Apply the file's .mmap_prepare() hook to an - * existing VMA and execute any requested actions. - * @file: The file which possesss an f_op->mmap_prepare() hook. - * @vma: The VMA to apply the .mmap_prepare() hook to. - * - * Ordinarily, .mmap_prepare() is invoked directly upon mmap(). However, c= ertain - * stacked filesystems invoke a nested mmap hook of an underlying file. - * - * Until all filesystems are converted to use .mmap_prepare(), we must be - * conservative and continue to invoke these stacked filesystems using the - * deprecated .mmap() hook. - * - * However we have a problem if the underlying file system possesses an - * .mmap_prepare() hook, as we are in a different context when we invoke t= he - * .mmap() hook, already having a VMA to deal with. - * - * compat_vma_mmap() is a compatibility function that takes VMA state, - * establishes a struct vm_area_desc descriptor, passes to the underlying - * .mmap_prepare() hook and applies any changes performed by it. - * - * Once the conversion of filesystems is complete this function will no lo= nger - * be required and will be removed. - * - * Returns: 0 on success or error. - */ -int compat_vma_mmap(struct file *file, struct vm_area_struct *vma) +static int __compat_vma_mmap(struct file *file, struct vm_area_struct *vma) { struct vm_area_desc desc =3D { .mm =3D vma->vm_mm, @@ -1221,8 +1195,49 @@ int compat_vma_mmap(struct file *file, struct vm_are= a_struct *vma) set_vma_from_desc(vma, &desc); return mmap_action_complete(vma, action); } + +/** + * compat_vma_mmap() - Apply the file's .mmap_prepare() hook to an + * existing VMA and execute any requested actions. + * @file: The file which possesss an f_op->mmap_prepare() hook. + * @vma: The VMA to apply the .mmap_prepare() hook to. + * + * Ordinarily, .mmap_prepare() is invoked directly upon mmap(). However, c= ertain + * stacked filesystems invoke a nested mmap hook of an underlying file. + * + * Until all filesystems are converted to use .mmap_prepare(), we must be + * conservative and continue to invoke these stacked filesystems using the + * deprecated .mmap() hook. + * + * However we have a problem if the underlying file system possesses an + * .mmap_prepare() hook, as we are in a different context when we invoke t= he + * .mmap() hook, already having a VMA to deal with. + * + * compat_vma_mmap() is a compatibility function that takes VMA state, + * establishes a struct vm_area_desc descriptor, passes to the underlying + * .mmap_prepare() hook and applies any changes performed by it. + * + * Once the conversion of filesystems is complete this function will no lo= nger + * be required and will be removed. + * + * Returns: 0 on success or error. + */ +int compat_vma_mmap(struct file *file, struct vm_area_struct *vma) +{ + return __compat_vma_mmap(file, vma); +} EXPORT_SYMBOL(compat_vma_mmap); =20 +int __vma_check_mmap_hook(struct vm_area_struct *vma) +{ + /* vm_ops->mapped is not valid if mmap() is specified. */ + if (vma->vm_ops && WARN_ON_ONCE(vma->vm_ops->mapped)) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(__vma_check_mmap_hook); + static void set_ps_flags(struct page_snapshot *ps, const struct folio *fol= io, const struct page *page) { @@ -1311,11 +1326,32 @@ void snapshot_page(struct page_snapshot *ps, const = struct page *page) } } =20 +static int call_vma_mapped(struct vm_area_struct *vma) +{ + const struct vm_operations_struct *vm_ops =3D vma->vm_ops; + void *vm_private_data =3D vma->vm_private_data; + int err; + + if (!vm_ops || !vm_ops->mapped) + return 0; + + err =3D vm_ops->mapped(vma->vm_start, vma->vm_end, vma->vm_pgoff, + vma->vm_file, &vm_private_data); + if (err) + return err; + + if (vm_private_data !=3D vma->vm_private_data) + vma->vm_private_data =3D vm_private_data; + return 0; +} + static int mmap_action_finish(struct vm_area_struct *vma, struct mmap_action *action, int err) { size_t len; =20 + if (!err) + err =3D call_vma_mapped(vma); if (!err && action->success_hook) err =3D action->success_hook(vma); =20 diff --git a/mm/vma.c b/mm/vma.c index 86f947c90442..2d631db272e6 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -2782,7 +2782,6 @@ static unsigned long __mmap_region(struct file *file,= unsigned long addr, =20 if (have_mmap_prepare && allocated_new) { error =3D mmap_action_complete(vma, &desc.action); - if (error) return error; } diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index bf8cffe1ea58..b4b12fc742c1 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -643,6 +643,23 @@ struct vm_operations_struct { * Context: User context. May sleep. Caller holds mmap_lock. */ void (*close)(struct vm_area_struct *vma); + /** + * @mapped: Called when the VMA is first mapped in the MM. Not called if + * the new VMA is merged with an adjacent VMA. + * + * The @vm_private_data field is an output field allowing the user to + * modify vma->vm_private_data as necessary. + * + * ONLY valid if set from f_op->mmap_prepare. Will result in an error if + * set from f_op->mmap. + * + * Returns %0 on success, or an error otherwise. On error, the VMA will + * be unmapped. + * + * Context: User context. May sleep. Caller holds mmap_lock. + */ + int (*mapped)(unsigned long start, unsigned long end, pgoff_t pgoff, + const struct file *file, void **vm_private_data); /* Called any time before splitting to check if it's allowed */ int (*may_split)(struct vm_area_struct *vma, unsigned long addr); int (*mremap)(struct vm_area_struct *vma); --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 285843CCFB8; Fri, 20 Mar 2026 22:40:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046432; cv=none; b=VlSbn/f/LyMX9doI0WRXOojVq3xZaDdHvKLcjvXMJaRcd6Szz0/Bs95hREATpglhDQudPflDLVSLdwUctbAaWAOcLgUb0Bh15DD6HIBXBOTNIOvO+N6j6iixPPcdphVR8FKm7WCgBGlMUxlxJlyVrWPcUyDCc5cdF+h69NvNv9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046432; c=relaxed/simple; bh=Luge2LcM06n2SwdrkjrO2DwOaqu0iDXh4dllLKz3Bdw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LqztN8SsF1f1OxgetW5kQBVzjzp+on8Ms7BIDydv+vXaLwVmpBLVSJ50o0RLpkEkv/BRGlnYiWY58vbKU7pZmu3OK7jrITxRzRzmtvF9qnPrdF8w2Bc7gnbBJSiRqlN6O1/ak3wkcNbQGeUyQsw/J8ZlYy1w8sco39myv0m1baM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uMfCOaMY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uMfCOaMY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40593C4CEF7; Fri, 20 Mar 2026 22:40:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046431; bh=Luge2LcM06n2SwdrkjrO2DwOaqu0iDXh4dllLKz3Bdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uMfCOaMYXg1BaHfL5Xiiept3qlEDKI46B8rP4kN9UP55h4jDK25wfAnhFC/1We7RY 7pIBQMIzfZ+JcW+sp89HeSHcKoOkzKuqlM1Z6GbtMVDXz5gOjPBu1/u9dwGi0UWGQs kcO5dDATOI1JVWz+A8kCz+3+XJL4Jtf+25Wbtj6TLZWHktMhmLKQPru+RQD/wL4PtB 1m2QSDQb/5aZqO7bJUnb9j78yorYoZ1ZZg8/H3TcJJT2t9nAIv6h8wU1i4LQndST9V 1WqCNRiMmXHTyTvP+j0shuaa/6nqBB1U9fQs7YoseEpTBNqk29Oqnvdclpa/lcWlXf qbyyCSL6nSnwQ== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 09/21] fs: afs: revert mmap_prepare() change Date: Fri, 20 Mar 2026 22:39:35 +0000 Message-ID: <08804c94e39d9102a3a8fbd12385e8aa079ba1d3.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Partially reverts commit 9d5403b1036c ("fs: convert most other generic_file_*mmap() users to .mmap_prepare()"). This is because the .mmap invocation establishes a refcount, but .mmap_prepare is called at a point where a merge or an allocation failure might happen after the call, which would leak the refcount increment. Functionality is being added to permit the use of .mmap_prepare in this case, but in the interim, we need to fix this. Fixes: 9d5403b1036c ("fs: convert most other generic_file_*mmap() users to = .mmap_prepare()") Cc: Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- fs/afs/file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index f609366fd2ac..74d04af51ff4 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -19,7 +19,7 @@ #include #include "internal.h" =20 -static int afs_file_mmap_prepare(struct vm_area_desc *desc); +static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); =20 static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *ite= r); static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos, @@ -35,7 +35,7 @@ const struct file_operations afs_file_operations =3D { .llseek =3D generic_file_llseek, .read_iter =3D afs_file_read_iter, .write_iter =3D netfs_file_write_iter, - .mmap_prepare =3D afs_file_mmap_prepare, + .mmap =3D afs_file_mmap, .splice_read =3D afs_file_splice_read, .splice_write =3D iter_file_splice_write, .fsync =3D afs_fsync, @@ -492,16 +492,16 @@ static void afs_drop_open_mmap(struct afs_vnode *vnod= e) /* * Handle setting up a memory mapping on an AFS file. */ -static int afs_file_mmap_prepare(struct vm_area_desc *desc) +static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) { - struct afs_vnode *vnode =3D AFS_FS_I(file_inode(desc->file)); + struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); int ret; =20 afs_add_open_mmap(vnode); =20 - ret =3D generic_file_mmap_prepare(desc); + ret =3D generic_file_mmap(file, vma); if (ret =3D=3D 0) - desc->vm_ops =3D &afs_vm_ops; + vma->vm_ops =3D &afs_vm_ops; else afs_drop_open_mmap(vnode); return ret; --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E53583D566B; Fri, 20 Mar 2026 22:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046435; cv=none; b=cipCTZJwcXYO2QLmNzWfT+n0a3VCw4IFmg0vRxkBUiMF7ba44aeYnq3nIlkQwr+CUiwunLo2DhXql47q+/MlIFI9Hz81E06UTjzbtnjWU89OVyOY0rCgSUOXXUQoePr+i2RKhtuHnyMtQ/mimwKYi70GAguoWHvSpFmLp7iJ8cQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046435; c=relaxed/simple; bh=zfhQBezGG5IcURkg0NJT+vOaS0gfqxyLqpHHVrI7cmM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W6u4wDGpZz2kPJqT9Vrgf7o/CPaqnW7AJnY0y/W/EfX4OteVclHaeApuGijfLWFlK4UXgGwAq7ywZD3UZv9wXJHpSf/k+koujIhEahA/0mWXerqbhqdu3yfHwxkUijZjpzY6eK6cB8FUh0P97BxRlh78XG5/uS5nRNkYGIwcjJs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oc7nm0wv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oc7nm0wv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F0D30C2BCB0; Fri, 20 Mar 2026 22:40:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046434; bh=zfhQBezGG5IcURkg0NJT+vOaS0gfqxyLqpHHVrI7cmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oc7nm0wvIPI8zRhE2sWNIsoZqJNkcj0rKW7f0P6BhLrYg79O6iX1NqkqqQ80fWOR1 /8lL3U0nYtBz34iD8QnhN/OAO9e3BhyKs/Tr+e4lZC2PPMPfdc1irVXs0TrXzvdrLL GULWFOngwHrBiDXdseBMhd9km9NNqODvNvAPRUS667fmC5Z/ZQzeO+wNaVlOCHXIt5 pWhoTCZSaXBw8Qo2kr5dSs59RKsbk9m0efXCfRx5rgsTQGkqEayyuTYSQSjLqw56b+ eHlg1g5RfTijTn5ubMEusLGvXB8kf3KoxQPbuktXUTyTEnRV487+vCsOxH0mhJsV3K VEOZGrCj6xEOg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 10/21] fs: afs: restore mmap_prepare implementation Date: Fri, 20 Mar 2026 22:39:36 +0000 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit 9d5403b1036c ("fs: convert most other generic_file_*mmap() users to .mmap_prepare()") updated AFS to use the mmap_prepare callback in favour of the deprecated mmap callback. However, it did not account for the fact that mmap_prepare is called pre-merge, and may then be merged, nor that mmap_prepare can fail to map due to an out of memory error. This change was therefore since reverted. Both of those are cases in which we should not be incrementing a reference count. With the newly added vm_ops->mapped callback available, we can simply defer this operation to that callback which is only invoked once the mapping is successfully in place (but not yet visible to userspace as the mmap and VMA write locks are held). This allows us to once again reimplement the .mmap_prepare implementation for this file system. Therefore add afs_mapped() to implement this callback for AFS, and remove the code doing so in afs_mmap_prepare(). Also update afs_vm_open(), afs_vm_close() and afs_vm_map_pages() to be consistent in how the vnode is accessed. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- fs/afs/file.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/fs/afs/file.c b/fs/afs/file.c index 74d04af51ff4..85696ac984cc 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -19,7 +19,7 @@ #include #include "internal.h" -static int afs_file_mmap(struct file *file, struct vm_area_struct *vma); +static int afs_file_mmap_prepare(struct vm_area_desc *desc); static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *ite= r); static ssize_t afs_file_splice_read(struct file *in, loff_t *ppos, @@ -28,6 +28,8 @@ static ssize_t afs_file_splice_read(struct file *in, loff= _t *ppos, static void afs_vm_open(struct vm_area_struct *area); static void afs_vm_close(struct vm_area_struct *area); static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgo= ff, pgoff_t end_pgoff); +static int afs_mapped(unsigned long start, unsigned long end, pgoff_t pgof= f, + const struct file *file, void **vm_private_data); const struct file_operations afs_file_operations =3D { .open =3D afs_open, @@ -35,7 +37,7 @@ const struct file_operations afs_file_operations =3D { .llseek =3D generic_file_llseek, .read_iter =3D afs_file_read_iter, .write_iter =3D netfs_file_write_iter, - .mmap =3D afs_file_mmap, + .mmap_prepare =3D afs_file_mmap_prepare, .splice_read =3D afs_file_splice_read, .splice_write =3D iter_file_splice_write, .fsync =3D afs_fsync, @@ -61,6 +63,7 @@ const struct address_space_operations afs_file_aops =3D { }; static const struct vm_operations_struct afs_vm_ops =3D { + .mapped =3D afs_mapped, .open =3D afs_vm_open, .close =3D afs_vm_close, .fault =3D filemap_fault, @@ -492,34 +495,47 @@ static void afs_drop_open_mmap(struct afs_vnode *vnod= e) /* * Handle setting up a memory mapping on an AFS file. */ -static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) +static int afs_file_mmap_prepare(struct vm_area_desc *desc) { - struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); int ret; - afs_add_open_mmap(vnode); + ret =3D generic_file_mmap_prepare(desc); + if (ret) + return ret; - ret =3D generic_file_mmap(file, vma); - if (ret =3D=3D 0) - vma->vm_ops =3D &afs_vm_ops; - else - afs_drop_open_mmap(vnode); + desc->vm_ops =3D &afs_vm_ops; return ret; } +static int afs_mapped(unsigned long start, unsigned long end, pgoff_t pgof= f, + const struct file *file, void **vm_private_data) +{ + struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); + + afs_add_open_mmap(vnode); + return 0; +} + static void afs_vm_open(struct vm_area_struct *vma) { - afs_add_open_mmap(AFS_FS_I(file_inode(vma->vm_file))); + struct file *file =3D vma->vm_file; + struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); + + afs_add_open_mmap(vnode); } static void afs_vm_close(struct vm_area_struct *vma) { - afs_drop_open_mmap(AFS_FS_I(file_inode(vma->vm_file))); + struct file *file =3D vma->vm_file; + struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); + + afs_drop_open_mmap(vnode); } static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgo= ff, pgoff_t end_pgoff) { - struct afs_vnode *vnode =3D AFS_FS_I(file_inode(vmf->vma->vm_file)); + struct file *file =3D vmf->vma->vm_file; + struct afs_vnode *vnode =3D AFS_FS_I(file_inode(file)); if (afs_check_validity(vnode)) return filemap_map_pages(vmf, start_pgoff, end_pgoff); -- 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E18893D3302; Fri, 20 Mar 2026 22:40:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046438; cv=none; b=nXOPF7gd0oIpmeNvLxnwX0pwH4MbD+n141Hf49aQDApfIhykT1Qf1R0bOZ4TF02hYgQRnfMm+qRSI+o5tu+F10VireDBfsSSgYCe7fLzeqk89/UgLZGcVW0rqx/Y6aP4tszfUlVqIgtbU0H2QsaAdVqO6j8xXmKC1uNrFFvvq88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046438; c=relaxed/simple; bh=WLjRSxKdtoiEWEPvion/ECuNEhc+IOVRePndNVfMfzs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qh5nDCWi95sKmwo0BG1FCmx9CwUkEQDtSCzF9SNj7A/uuTJ+iASJwpIHix87k8adXDCYF3V2GEz9jMPbrOqS9BfPRB4G4jFYZdvt581+cOlsVYG9/5dVfgEk33Q8rkMQjMLiFFrV6zXlFCkkZzGeu/sdnKvlaUUURl+U2KooAJ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BdAFfXV7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BdAFfXV7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CAF97C2BCB1; Fri, 20 Mar 2026 22:40:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046437; bh=WLjRSxKdtoiEWEPvion/ECuNEhc+IOVRePndNVfMfzs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BdAFfXV734Lj8dQR7IZAo5MEH25Ec75BNmDza71k5A/MGmWJWabwF3XnhqA9JdZmL pOc0Ti2DICfMKIf4GoXwUzrY/W8YjU+pP0Ph/hxR9g6K1e9k4RmBNj5nKu7ys6+jll SOvAGGv5SD2fAGANGZGhgb2SNUO+ZzEE6IqLnppAIKCRrwLjRt2uh55XKVDgH9KU95 86DYh+3A3N7xe7RzjTLmiAZJKI1xgWZWYS56m1KgBdP1U2CDFwPsm+6wxZ+uprkjnn huAzvSWqvNA8tRmYvhT4E4YZcCNODugdKpcX/GAopZqsPpZj3mDlIsm+KAbikdLis8 H1jDU6YIHHBDA== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 11/21] mm: add mmap_action_simple_ioremap() Date: Fri, 20 Mar 2026 22:39:37 +0000 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently drivers use vm_iomap_memory() as a simple helper function for I/O remapping memory over a range starting at a specified physical address over a specified length. In order to utilise this from mmap_prepare, separate out the core logic into __simple_ioremap_prep(), update vm_iomap_memory() to use it, and add simple_ioremap_prepare() to do the same with a VMA descriptor object. We also add MMAP_SIMPLE_IO_REMAP and relevant fields to the struct mmap_action type to permit this operation also. We use mmap_action_ioremap() to set up the actual I/O remap operation once we have checked and figured out the parameters, which makes simple_ioremap_prepare() easy to implement. We then add mmap_action_simple_ioremap() to allow drivers to make use of this mode. We update the mmap_prepare documentation to describe this mode. Finally, we update the VMA tests to reflect this change. Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- Documentation/filesystems/mmap_prepare.rst | 3 + include/linux/mm.h | 24 +++++- include/linux/mm_types.h | 6 +- mm/internal.h | 1 + mm/memory.c | 85 +++++++++++++++------- mm/util.c | 5 ++ tools/testing/vma/include/dup.h | 6 +- 7 files changed, 102 insertions(+), 28 deletions(-) diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/fil= esystems/mmap_prepare.rst index f14b35ee11d5..14bb057be564 100644 --- a/Documentation/filesystems/mmap_prepare.rst +++ b/Documentation/filesystems/mmap_prepare.rst @@ -153,5 +153,8 @@ pointer. These are: * mmap_action_ioremap_full() - Same as mmap_action_ioremap(), only remaps the entire mapping from ``start_pfn`` onward. =20 +* mmap_action_simple_ioremap() - Sets up an I/O remap from a specified + physical address and over a specified length. + **NOTE:** The ``action`` field should never normally be manipulated direct= ly, rather you ought to use one of these helpers. diff --git a/include/linux/mm.h b/include/linux/mm.h index ad1b8c3c0cfd..df8fa6e6402b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4337,11 +4337,33 @@ static inline void mmap_action_ioremap(struct vm_ar= ea_desc *desc, * @start_pfn: The first PFN in the range to remap. */ static inline void mmap_action_ioremap_full(struct vm_area_desc *desc, - unsigned long start_pfn) + unsigned long start_pfn) { mmap_action_ioremap(desc, desc->start, start_pfn, vma_desc_size(desc)); } =20 +/** + * mmap_action_simple_ioremap - helper for mmap_prepare hook to specify th= at the + * physical range in [start_phys_addr, start_phys_addr + size) should be I= /O + * remapped. + * @desc: The VMA descriptor for the VMA requiring remap. + * @start_phys_addr: Start of the physical memory to be mapped. + * @size: Size of the area to map. + * + * NOTE: Some drivers might want to tweak desc->page_prot for purposes of + * write-combine or similar. + */ +static inline void mmap_action_simple_ioremap(struct vm_area_desc *desc, + phys_addr_t start_phys_addr, + unsigned long size) +{ + struct mmap_action *action =3D &desc->action; + + action->simple_ioremap.start_phys_addr =3D start_phys_addr; + action->simple_ioremap.size =3D size; + action->type =3D MMAP_SIMPLE_IO_REMAP; +} + int mmap_action_prepare(struct vm_area_desc *desc); int mmap_action_complete(struct vm_area_struct *vma, struct mmap_action *action); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 16d31045e26e..174286f9ecf0 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -814,6 +814,7 @@ enum mmap_action_type { MMAP_NOTHING, /* Mapping is complete, no further action. */ MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ + MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ }; =20 /* @@ -822,13 +823,16 @@ enum mmap_action_type { */ struct mmap_action { union { - /* Remap range. */ struct { unsigned long start; unsigned long start_pfn; unsigned long size; pgprot_t pgprot; } remap; + struct { + phys_addr_t start_phys_addr; + unsigned long size; + } simple_ioremap; }; enum mmap_action_type type; =20 diff --git a/mm/internal.h b/mm/internal.h index 760fbff9c430..46cc1a695a0e 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1796,6 +1796,7 @@ int dup_mmap(struct mm_struct *mm, struct mm_struct *= oldmm); int remap_pfn_range_prepare(struct vm_area_desc *desc); int remap_pfn_range_complete(struct vm_area_struct *vma, struct mmap_action *action); +int simple_ioremap_prepare(struct vm_area_desc *desc); =20 static inline int io_remap_pfn_range_prepare(struct vm_area_desc *desc) { diff --git a/mm/memory.c b/mm/memory.c index 9dec67a18116..b3bcc21af20a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3170,6 +3170,58 @@ int remap_pfn_range_complete(struct vm_area_struct *= vma, return do_remap_pfn_range(vma, start, pfn, size, prot); } =20 +static int __simple_ioremap_prep(unsigned long vm_len, pgoff_t vm_pgoff, + phys_addr_t start_phys, unsigned long size, + unsigned long *pfnp) +{ + unsigned long pfn, pages; + + /* Check that the physical memory area passed in looks valid */ + if (start_phys + size < start_phys) + return -EINVAL; + /* + * You *really* shouldn't map things that aren't page-aligned, + * but we've historically allowed it because IO memory might + * just have smaller alignment. + */ + size +=3D start_phys & ~PAGE_MASK; + pfn =3D start_phys >> PAGE_SHIFT; + pages =3D (size + ~PAGE_MASK) >> PAGE_SHIFT; + if (pfn + pages < pfn) + return -EINVAL; + + /* We start the mapping 'vm_pgoff' pages into the area */ + if (vm_pgoff > pages) + return -EINVAL; + pfn +=3D vm_pgoff; + pages -=3D vm_pgoff; + + /* Can we fit all of the mapping? */ + if ((vm_len >> PAGE_SHIFT) > pages) + return -EINVAL; + + *pfnp =3D pfn; + return 0; +} + +int simple_ioremap_prepare(struct vm_area_desc *desc) +{ + struct mmap_action *action =3D &desc->action; + const phys_addr_t start =3D action->simple_ioremap.start_phys_addr; + const unsigned long size =3D action->simple_ioremap.size; + unsigned long pfn; + int err; + + err =3D __simple_ioremap_prep(vma_desc_size(desc), desc->pgoff, + start, size, &pfn); + if (err) + return err; + + /* The I/O remap logic does the heavy lifting. */ + mmap_action_ioremap_full(desc, pfn); + return io_remap_pfn_range_prepare(desc); +} + /** * vm_iomap_memory - remap memory to userspace * @vma: user vma to map to @@ -3187,32 +3239,15 @@ int remap_pfn_range_complete(struct vm_area_struct = *vma, */ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigne= d long len) { - unsigned long vm_len, pfn, pages; - - /* Check that the physical memory area passed in looks valid */ - if (start + len < start) - return -EINVAL; - /* - * You *really* shouldn't map things that aren't page-aligned, - * but we've historically allowed it because IO memory might - * just have smaller alignment. - */ - len +=3D start & ~PAGE_MASK; - pfn =3D start >> PAGE_SHIFT; - pages =3D (len + ~PAGE_MASK) >> PAGE_SHIFT; - if (pfn + pages < pfn) - return -EINVAL; - - /* We start the mapping 'vm_pgoff' pages into the area */ - if (vma->vm_pgoff > pages) - return -EINVAL; - pfn +=3D vma->vm_pgoff; - pages -=3D vma->vm_pgoff; + const unsigned long vm_start =3D vma->vm_start; + const unsigned long vm_end =3D vma->vm_end; + const unsigned long vm_len =3D vm_end - vm_start; + unsigned long pfn; + int err; =20 - /* Can we fit all of the mapping? */ - vm_len =3D vma->vm_end - vma->vm_start; - if (vm_len >> PAGE_SHIFT > pages) - return -EINVAL; + err =3D __simple_ioremap_prep(vm_len, vma->vm_pgoff, start, len, &pfn); + if (err) + return err; =20 /* Ok, let it rip */ return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_p= rot); diff --git a/mm/util.c b/mm/util.c index df95ae41e09b..a19f062b84dc 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1393,6 +1393,8 @@ int mmap_action_prepare(struct vm_area_desc *desc) return remap_pfn_range_prepare(desc); case MMAP_IO_REMAP_PFN: return io_remap_pfn_range_prepare(desc); + case MMAP_SIMPLE_IO_REMAP: + return simple_ioremap_prepare(desc); } =20 WARN_ON_ONCE(1); @@ -1421,6 +1423,7 @@ int mmap_action_complete(struct vm_area_struct *vma, err =3D remap_pfn_range_complete(vma, action); break; case MMAP_IO_REMAP_PFN: + case MMAP_SIMPLE_IO_REMAP: /* Should have been delegated. */ WARN_ON_ONCE(1); err =3D -EINVAL; @@ -1438,6 +1441,7 @@ int mmap_action_prepare(struct vm_area_desc *desc) break; case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: + case MMAP_SIMPLE_IO_REMAP: WARN_ON_ONCE(1); /* nommu cannot handle these. */ break; } @@ -1456,6 +1460,7 @@ int mmap_action_complete(struct vm_area_struct *vma, break; case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: + case MMAP_SIMPLE_IO_REMAP: WARN_ON_ONCE(1); /* nommu cannot handle this. */ =20 err =3D -EINVAL; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index b4b12fc742c1..a0c2379bd42b 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -453,6 +453,7 @@ enum mmap_action_type { MMAP_NOTHING, /* Mapping is complete, no further action. */ MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ + MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ }; =20 /* @@ -461,13 +462,16 @@ enum mmap_action_type { */ struct mmap_action { union { - /* Remap range. */ struct { unsigned long start; unsigned long start_pfn; unsigned long size; pgprot_t pgprot; } remap; + struct { + phys_addr_t start_phys_addr; + unsigned long size; + } simple_ioremap; }; enum mmap_action_type type; =20 --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 944223ED5D4; Fri, 20 Mar 2026 22:40:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046440; cv=none; b=WvkJ6Sa1AnAz2OWJVLZsEHTiZCBA0YSUM3oHpmr0MIv2iukOfJtFSaL6upa2U9EnWGqcj7rIBdML40YphYGv5LSzp2jX/82WKLeJr3SI54H2s3iUUI+MjBJeEIhyIAVOuRTcUf4UvbcLc/m5MWSfezhwtT0sv01Sr/btWoTp5QE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046440; c=relaxed/simple; bh=zxWNAJj7O8GtoZ6ysYQIGq3mbn9MaN35AkA3dod/SuI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KvS4SJz66fDnw2qxR05NZAcE3QmCqUW8oM71iSK9tdMRNlBkq3uPDrGhfaWfm17gord/fNmE3sN+q/NvDoSbWOzt0oT7zoCaxjlz9fqBzCgS1WP556/u6b16oJe41eAK84le3M5L2oeI7Kf6QOFdGe8oZFbg8nE1GHFAldQHTdk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YHaH69Mn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YHaH69Mn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A408AC2BC9E; Fri, 20 Mar 2026 22:40:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046440; bh=zxWNAJj7O8GtoZ6ysYQIGq3mbn9MaN35AkA3dod/SuI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YHaH69MnrwnjEExESD+N74FB5sHGoJU4Jzp13qn42CieQKBElreTDK4ABKOTkKI9E YVJEQk7Igps5UHFr1QkcNviCX9tiSeCorYcocEKZGuSjbBmhXF1i/McLQmQzd/BvQU GwI4GRVLdXYDi8yLWVHQ9xx1hoS5xAYim9x1t09OJL4K+HgRfFl+5opDDkIHW80Wcw G6sat1uwi9u+56yN/eGbFeoa/9Cs5QGbj5T35mAAZdIpfscfYs6Vrish6ZooqG2kPg bkWKOcBQL5PZbrvNoj0VU0bO6v6Z2M7tEtp3VkTBumY6frrxHwXL/gBDIR57u/+hys aDSMuS29n0SZw== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 12/21] misc: open-dice: replace deprecated mmap hook with mmap_prepare Date: Fri, 20 Mar 2026 22:39:38 +0000 Message-ID: <5a83ab00195dc8d0609fa6cc525493010ac4ead1.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update driver to use its successor, mmap_prepare. The driver previously used vm_iomap_memory(), so this change replaces it with its mmap_prepare equivalent, mmap_action_simple_ioremap(). Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/misc/open-dice.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/misc/open-dice.c b/drivers/misc/open-dice.c index 24c29e0f00ef..45060fb4ea27 100644 --- a/drivers/misc/open-dice.c +++ b/drivers/misc/open-dice.c @@ -86,29 +86,32 @@ static ssize_t open_dice_write(struct file *filp, const= char __user *ptr, /* * Creates a mapping of the reserved memory region in user address space. */ -static int open_dice_mmap(struct file *filp, struct vm_area_struct *vma) +static int open_dice_mmap_prepare(struct vm_area_desc *desc) { + struct file *filp =3D desc->file; struct open_dice_drvdata *drvdata =3D to_open_dice_drvdata(filp); =20 - if (vma->vm_flags & VM_MAYSHARE) { + if (vma_desc_test(desc, VMA_MAYSHARE_BIT)) { /* Do not allow userspace to modify the underlying data. */ - if (vma->vm_flags & VM_WRITE) + if (vma_desc_test(desc, VMA_WRITE_BIT)) return -EPERM; /* Ensure userspace cannot acquire VM_WRITE later. */ - vm_flags_clear(vma, VM_MAYWRITE); + vma_desc_clear_flags(desc, VMA_MAYWRITE_BIT); } =20 /* Create write-combine mapping so all clients observe a wipe. */ - vma->vm_page_prot =3D pgprot_writecombine(vma->vm_page_prot); - vm_flags_set(vma, VM_DONTCOPY | VM_DONTDUMP); - return vm_iomap_memory(vma, drvdata->rmem->base, drvdata->rmem->size); + desc->page_prot =3D pgprot_writecombine(desc->page_prot); + vma_desc_set_flags(desc, VMA_DONTCOPY_BIT, VMA_DONTDUMP_BIT); + mmap_action_simple_ioremap(desc, drvdata->rmem->base, + drvdata->rmem->size); + return 0; } =20 static const struct file_operations open_dice_fops =3D { .owner =3D THIS_MODULE, .read =3D open_dice_read, .write =3D open_dice_write, - .mmap =3D open_dice_mmap, + .mmap_prepare =3D open_dice_mmap_prepare, }; =20 static int __init open_dice_probe(struct platform_device *pdev) --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1D6AF3ECBD0; Fri, 20 Mar 2026 22:40:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046443; cv=none; b=UAa/t6vGn+cC1P0k29kZy/1tPbEUdjakbN5F8TSLCxQ+ECWoEU+QkNDOkpXOsft1ZVkOhdyNSv5xpKjhgPFHQrP5azxraPVAD9ZsFcxb+EYS1oMmrxtcCqO5deF5f6AEpYe8g5AQOOD8LDmebtqmeIUHtpcOYZts7+gRJUGNh58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046443; c=relaxed/simple; bh=LhT0XvoqFL5inoAn3uLwrHjF8WgiWC6oU1y5hKpoQX4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fDZenYo0oR2Y9E1O9BdYSeyORnvz5Fsyws+Ik7hB2/4qipi3ro0SCRp9CRVtVhEaECwa1j4/LZlNQ45bTYCJvJ/CGhw1AbzKso0xd3anXNQ8mJqrXnq4ScGohC2ht8yUmcaNPwD9mftNhKkCInsANPacZ07YnL+mw6IZiVMvWq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=l4wHJxsh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="l4wHJxsh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 64DC0C2BCB2; Fri, 20 Mar 2026 22:40:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046443; bh=LhT0XvoqFL5inoAn3uLwrHjF8WgiWC6oU1y5hKpoQX4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l4wHJxsh7bYrI5l9ypzEJJtRUNeMWoz2qQ6/CYcGcW6jBmZWlRSJKuTUhZQe/WKcc VsRAogHYE/GMTSF9k7KQwCnYeraYqnjeiTQJaiZBwJd5wOH1b5ayrRDW5yDMQKY6dy bW61X0wOKU66c5WTPw0B4hbi18iGnFEHGTz0G67J9Z6ohhrp6ooCSCEj89MEkcqpqQ DBw1rYls5FAig8H/X2et7iKJdCKYxZ3BBE/j4VlCfyTSw9b6kXjs+yVPrNaB4Jc0wx j64mDAAaOvoFQEKZ6nZg2+wIkP8ME7WDB+olROlFem2adm+nNFPwxfPpzTeZ7TkxD6 hVTZFsJ0VtaSw== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 13/21] hpet: replace deprecated mmap hook with mmap_prepare Date: Fri, 20 Mar 2026 22:39:39 +0000 Message-ID: <094c5fcfb2459a4f6d791b1fb852b01e252a44d4.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update driver to use its successor, mmap_prepare. The driver previously used vm_iomap_memory(), so this change replaces it with its mmap_prepare equivalent, mmap_action_simple_ioremap(). Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/char/hpet.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 60dd09a56f50..8f128cc40147 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -354,8 +354,9 @@ static __init int hpet_mmap_enable(char *str) } __setup("hpet_mmap=3D", hpet_mmap_enable); =20 -static int hpet_mmap(struct file *file, struct vm_area_struct *vma) +static int hpet_mmap_prepare(struct vm_area_desc *desc) { + struct file *file =3D desc->file; struct hpet_dev *devp; unsigned long addr; =20 @@ -368,11 +369,12 @@ static int hpet_mmap(struct file *file, struct vm_are= a_struct *vma) if (addr & (PAGE_SIZE - 1)) return -ENOSYS; =20 - vma->vm_page_prot =3D pgprot_noncached(vma->vm_page_prot); - return vm_iomap_memory(vma, addr, PAGE_SIZE); + desc->page_prot =3D pgprot_noncached(desc->page_prot); + mmap_action_simple_ioremap(desc, addr, PAGE_SIZE); + return 0; } #else -static int hpet_mmap(struct file *file, struct vm_area_struct *vma) +static int hpet_mmap_prepare(struct vm_area_desc *desc) { return -ENOSYS; } @@ -710,7 +712,7 @@ static const struct file_operations hpet_fops =3D { .open =3D hpet_open, .release =3D hpet_release, .fasync =3D hpet_fasync, - .mmap =3D hpet_mmap, + .mmap_prepare =3D hpet_mmap_prepare, }; =20 static int hpet_is_known(struct hpet_data *hdp) --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 292A12E1F11; Fri, 20 Mar 2026 22:40:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046446; cv=none; b=MdbijV2Yprr2Z411xSPap/6hagTmDcKw2k0QIza+AY00qFpj6oOXNNnzzmxQ6SIA7as9kMk9hKxZbfarvycEDU+eRg8iMQLoY3TKBoVFU1FKYXzumYjN52GbSk4jOBS5VcA8q6FWS9nMBmyP0VFvN5Pu4+FlWqiBMnJr4gk2lx4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046446; c=relaxed/simple; bh=sJsnVE59stSeWATG7qlVuZYBseXJSjXjZYGmtSdmRzo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uEPIaW7M+y6bkbAXcz5M8P6YQI8ArL7tkcBlz0oY6KQOGD/gUn1hYWwdv63Bo+aK8C7UPvho2mdXToaqBakvlpeRghDk76NXiWs+IUXx6D1D37SeoyQyNujB3WwF0Cbu9/ZYQKnxWCQkNhIOpkxQ7cb1nPT4xbxVetojd/EsarE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K1kclIJD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="K1kclIJD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3ECCFC4CEF7; Fri, 20 Mar 2026 22:40:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046445; bh=sJsnVE59stSeWATG7qlVuZYBseXJSjXjZYGmtSdmRzo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K1kclIJDvpcatekEIiKHG9JLd6yodFFlAIimrHkQrYpfpaP1j083wqjfQWuqEPaAW jK/AXSOIeeUMo2zyW/8jErZ2Ttt6yeHOlqzmSnEX0soB69ZhZQPdvd4Kkw+8F1ya/E Bhg55hrFfeQRgRtfiJH31w6IqxgqmTfzjKX9uzowCmnX4LQpdBAredD1TMCm85ytAJ 0T4oBFH4/404Ahf7q0mLNvE/PhIzDdEKpljKRgrEXbdFoEF4ZVatPwEanwAbtpUZdQ 8XCqkSS7grldEDxzRlQ8cWj2uKIUTeMDSAsVRTzI7glhE0bC9YnNsGvx2Qo2X6+Arm tf/+H4W3fsB2g== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 14/21] mtdchar: replace deprecated mmap hook with mmap_prepare, clean up Date: Fri, 20 Mar 2026 22:39:40 +0000 Message-ID: X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace the deprecated mmap callback with mmap_prepare. Commit f5cf8f07423b ("mtd: Disable mtdchar mmap on MMU systems") commented out the CONFIG_MMU part of this function back in 2012, so after ~14 years it's probably reasonable to remove this altogether rather than updating dead code. Acked-by: Richard Weinberger Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/mtd/mtdchar.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 55a43682c567..bf01e6ac7293 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1376,27 +1376,12 @@ static unsigned mtdchar_mmap_capabilities(struct fi= le *file) /* * set up a mapping for shared memory segments */ -static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma) +static int mtdchar_mmap_prepare(struct vm_area_desc *desc) { #ifdef CONFIG_MMU - struct mtd_file_info *mfi =3D file->private_data; - struct mtd_info *mtd =3D mfi->mtd; - struct map_info *map =3D mtd->priv; - - /* This is broken because it assumes the MTD device is map-based - and that mtd->priv is a valid struct map_info. It should be - replaced with something that uses the mtd_get_unmapped_area() - operation properly. */ - if (0 /*mtd->type =3D=3D MTD_RAM || mtd->type =3D=3D MTD_ROM*/) { -#ifdef pgprot_noncached - if (file->f_flags & O_DSYNC || map->phys >=3D __pa(high_memory)) - vma->vm_page_prot =3D pgprot_noncached(vma->vm_page_prot); -#endif - return vm_iomap_memory(vma, map->phys, map->size); - } return -ENODEV; #else - return vma->vm_flags & VM_SHARED ? 0 : -EACCES; + return vma_desc_test(desc, VMA_SHARED_BIT) ? 0 : -EACCES; #endif } =20 @@ -1411,7 +1396,7 @@ static const struct file_operations mtd_fops =3D { #endif .open =3D mtdchar_open, .release =3D mtdchar_close, - .mmap =3D mtdchar_mmap, + .mmap_prepare =3D mtdchar_mmap_prepare, #ifndef CONFIG_MMU .get_unmapped_area =3D mtdchar_get_unmapped_area, .mmap_capabilities =3D mtdchar_mmap_capabilities, --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2B6A3CB2FE; Fri, 20 Mar 2026 22:40:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046448; cv=none; b=FtHo4lDeYroZzScLp2Zqd0Ujc0fnG99EaX6a7rBAxE883+uTjIP9OzRBCa6936OFtThvjAM4S4G1HoyY0RBR7o0rZheS9qg+cxRYX3bvKVScOzo21dB7wBMR4SEALHqiJ9TKEThV3kL7u1uYos2eoATniFzEFhlX2NmLzPjBdsc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046448; c=relaxed/simple; bh=rC8UhPo2hXOr5FxBAlmEyrOxvDFCNwpWMS0HCPMZ5xQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KbD4ZbXH546WLR3HmFI5OHZEiNYqpJ1tt6HK2/w/BW0ujgwTCjgMhYcKTLKM0VAhqQ7NR+8A8wge4i6o5KByKZRCwZsdZ3FDuNw+dQ8HOJnFcceIUv/9itQe20M2UYjxPqtuibOpE2gIF6zpc1gzhh0+F2jreUhfCHvU1HH6/Qs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jDWrE0wg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jDWrE0wg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 063CBC4CEF7; Fri, 20 Mar 2026 22:40:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046448; bh=rC8UhPo2hXOr5FxBAlmEyrOxvDFCNwpWMS0HCPMZ5xQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jDWrE0wgPddZzCp/6MXK6JtMRXwDHcncD6Pj3A0RlrLa9zNX5JGIJM0U9t1UwvBN6 twzxYKnGdtV88a0F3yVb7GNg44xifk+XFDGN25B3mLjNPX8FneUvbLeJEQNdtUt+WZ /WH9NUWNCW6kMFTyjb+FmMKLFX2G4JaHL5+eGKdLNhbt7+v595DrvFQy6V7DTdK6hP V0/SMtHmbCkPbpX0kqrB4ikg8rPlyLYqzH6GDsIeQ1eCh6Fq+mPmF+bPpeusN4e5RB MrJLikSOWypIy40O2GVpU9qtXFTnNtyqLTtrhGWOpRG0RADI3LlJbe2hP9kqnW/0Ky XEbXUHAUYlzGA== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 15/21] stm: replace deprecated mmap hook with mmap_prepare Date: Fri, 20 Mar 2026 22:39:41 +0000 Message-ID: <9f3d559a264a83cf45518fcf35cc7ef1d7dfd500.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update driver to use its successor, mmap_prepare. The driver previously used vm_iomap_memory(), so this change replaces it with its mmap_prepare equivalent, mmap_action_simple_ioremap(). Also, in order to correctly maintain reference counting, add a vm_ops->mapped callback to increment the reference count when successfully mapped. Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/hwtracing/stm/core.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 37584e786bb5..f48c6a8a0654 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -666,6 +666,16 @@ static ssize_t stm_char_write(struct file *file, const= char __user *buf, return count; } =20 +static int stm_mmap_mapped(unsigned long start, unsigned long end, pgoff_t= pgoff, + const struct file *file, void **vm_private_data) +{ + struct stm_file *stmf =3D file->private_data; + struct stm_device *stm =3D stmf->stm; + + pm_runtime_get_sync(&stm->dev); + return 0; +} + static void stm_mmap_open(struct vm_area_struct *vma) { struct stm_file *stmf =3D vma->vm_file->private_data; @@ -684,12 +694,14 @@ static void stm_mmap_close(struct vm_area_struct *vma) } =20 static const struct vm_operations_struct stm_mmap_vmops =3D { + .mapped =3D stm_mmap_mapped, .open =3D stm_mmap_open, .close =3D stm_mmap_close, }; =20 -static int stm_char_mmap(struct file *file, struct vm_area_struct *vma) +static int stm_char_mmap_prepare(struct vm_area_desc *desc) { + struct file *file =3D desc->file; struct stm_file *stmf =3D file->private_data; struct stm_device *stm =3D stmf->stm; unsigned long size, phys; @@ -697,10 +709,10 @@ static int stm_char_mmap(struct file *file, struct vm= _area_struct *vma) if (!stm->data->mmio_addr) return -EOPNOTSUPP; =20 - if (vma->vm_pgoff) + if (desc->pgoff) return -EINVAL; =20 - size =3D vma->vm_end - vma->vm_start; + size =3D vma_desc_size(desc); =20 if (stmf->output.nr_chans * stm->data->sw_mmiosz !=3D size) return -EINVAL; @@ -712,13 +724,12 @@ static int stm_char_mmap(struct file *file, struct vm= _area_struct *vma) if (!phys) return -EINVAL; =20 - pm_runtime_get_sync(&stm->dev); - - vma->vm_page_prot =3D pgprot_noncached(vma->vm_page_prot); - vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_ops =3D &stm_mmap_vmops; - vm_iomap_memory(vma, phys, size); + desc->page_prot =3D pgprot_noncached(desc->page_prot); + vma_desc_set_flags(desc, VMA_IO_BIT, VMA_DONTEXPAND_BIT, + VMA_DONTDUMP_BIT); + desc->vm_ops =3D &stm_mmap_vmops; =20 + mmap_action_simple_ioremap(desc, phys, size); return 0; } =20 @@ -836,7 +847,7 @@ static const struct file_operations stm_fops =3D { .open =3D stm_char_open, .release =3D stm_char_release, .write =3D stm_char_write, - .mmap =3D stm_char_mmap, + .mmap_prepare =3D stm_char_mmap_prepare, .unlocked_ioctl =3D stm_char_ioctl, .compat_ioctl =3D compat_ptr_ioctl, }; --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2B6E3CB2FE; Fri, 20 Mar 2026 22:40:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046451; cv=none; b=cq3lMtcT03rzD3tniBfsiIryoc6Fo12dAq++/KM4oCZ3gtfSS2qtMOlkLFWhne2yeumu7wcwUssJMDsQG/aHXwxpL/wjeXD+YukIVEe0uZZ+OL0HO1eHWk0rObdxm934uYymDasaxWRu96PjXtMaynPShgmevvjy/2BR+iBVzgs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046451; c=relaxed/simple; bh=rywd1FEi1wWV4fl3gPPvz3vegyh8dDCmAT13xfhNCIY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T9yO8k2eEnjWjB1hQFlrnLREO4CCvgB2xjF4VXR4yJXj3usuP8+P8RJUeBB6KNKIcmLFDSR+LMWRj2rb9tMIeiUJjjI782OCswhnJDdSWS5JDHFCx+0FrGktmhS1BBuloxI76+sIK0MRadZDoBw9RsH9cNZCVFjSFRwlUI1L2Rw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Mzh/VzNf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Mzh/VzNf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BA946C4CEF7; Fri, 20 Mar 2026 22:40:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046451; bh=rywd1FEi1wWV4fl3gPPvz3vegyh8dDCmAT13xfhNCIY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Mzh/VzNfn6owZgsAvp11YUWy6Ov62q3AksJSQPQGotGTLaVk8DUWoGOSIuPJc2Skm GcNkj89ZRfB/AJhumMEGHyopvzejgPPjD5JMAqXv6ekioGaY6Wbgk99VTAfg81a4fg qkbjrAhoW8twMolBCVxcIPE5igQ8FEeeXR8AoONojgL/vaNxVDE2d6TlODG+3M8ZPD kKZ3aDnmBxV3JHk5JTfrvS9Zi8Ur8+j6R+VmxzzEj0iV4hxRnhBbqbqfFaig73ngbW 74lFPJeMzaejB5zScvPpsfMbHzCIr0pK3HWGQOCNcfheiHFK860SpEuHrdRp41KD/5 m5QwNoosDnA5Q== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 16/21] staging: vme_user: replace deprecated mmap hook with mmap_prepare Date: Fri, 20 Mar 2026 22:39:42 +0000 Message-ID: <08ecc1e1d319564fd49b9e9012f994edaff921db.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update driver to use its successor, mmap_prepare. The driver previously used vm_iomap_memory(), so this change replaces it with its mmap_prepare equivalent, mmap_action_simple_ioremap(). Functions that wrap mmap() are also converted to wrap mmap_prepare() instead. Also update the documentation accordingly. Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- Documentation/driver-api/vme.rst | 2 +- drivers/staging/vme_user/vme.c | 20 +++++------ drivers/staging/vme_user/vme.h | 2 +- drivers/staging/vme_user/vme_user.c | 51 +++++++++++++++++------------ 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/Documentation/driver-api/vme.rst b/Documentation/driver-api/vm= e.rst index c0b475369de0..7111999abc14 100644 --- a/Documentation/driver-api/vme.rst +++ b/Documentation/driver-api/vme.rst @@ -107,7 +107,7 @@ The function :c:func:`vme_master_read` can be used to r= ead from and =20 In addition to simple reads and writes, :c:func:`vme_master_rmw` is provid= ed to do a read-modify-write transaction. Parts of a VME window can also be mapp= ed -into user space memory using :c:func:`vme_master_mmap`. +into user space memory using :c:func:`vme_master_mmap_prepare`. =20 =20 Slave windows diff --git a/drivers/staging/vme_user/vme.c b/drivers/staging/vme_user/vme.c index f10a00c05f12..7220aba7b919 100644 --- a/drivers/staging/vme_user/vme.c +++ b/drivers/staging/vme_user/vme.c @@ -735,9 +735,9 @@ unsigned int vme_master_rmw(struct vme_resource *resour= ce, unsigned int mask, EXPORT_SYMBOL(vme_master_rmw); =20 /** - * vme_master_mmap - Mmap region of VME master window. + * vme_master_mmap_prepare - Mmap region of VME master window. * @resource: Pointer to VME master resource. - * @vma: Pointer to definition of user mapping. + * @desc: Pointer to descriptor of user mapping. * * Memory map a region of the VME master window into user space. * @@ -745,12 +745,13 @@ EXPORT_SYMBOL(vme_master_rmw); * resource or -EFAULT if map exceeds window size. Other generic m= map * errors may also be returned. */ -int vme_master_mmap(struct vme_resource *resource, struct vm_area_struct *= vma) +int vme_master_mmap_prepare(struct vme_resource *resource, + struct vm_area_desc *desc) { + const unsigned long vma_size =3D vma_desc_size(desc); struct vme_bridge *bridge =3D find_bridge(resource); struct vme_master_resource *image; phys_addr_t phys_addr; - unsigned long vma_size; =20 if (resource->type !=3D VME_MASTER) { dev_err(bridge->parent, "Not a master resource\n"); @@ -758,19 +759,18 @@ int vme_master_mmap(struct vme_resource *resource, st= ruct vm_area_struct *vma) } =20 image =3D list_entry(resource->entry, struct vme_master_resource, list); - phys_addr =3D image->bus_resource.start + (vma->vm_pgoff << PAGE_SHIFT); - vma_size =3D vma->vm_end - vma->vm_start; + phys_addr =3D image->bus_resource.start + (desc->pgoff << PAGE_SHIFT); =20 if (phys_addr + vma_size > image->bus_resource.end + 1) { dev_err(bridge->parent, "Map size cannot exceed the window size\n"); return -EFAULT; } =20 - vma->vm_page_prot =3D pgprot_noncached(vma->vm_page_prot); - - return vm_iomap_memory(vma, phys_addr, vma->vm_end - vma->vm_start); + desc->page_prot =3D pgprot_noncached(desc->page_prot); + mmap_action_simple_ioremap(desc, phys_addr, vma_size); + return 0; } -EXPORT_SYMBOL(vme_master_mmap); +EXPORT_SYMBOL(vme_master_mmap_prepare); =20 /** * vme_master_free - Free VME master window diff --git a/drivers/staging/vme_user/vme.h b/drivers/staging/vme_user/vme.h index 797e9940fdd1..b6413605ea49 100644 --- a/drivers/staging/vme_user/vme.h +++ b/drivers/staging/vme_user/vme.h @@ -151,7 +151,7 @@ ssize_t vme_master_read(struct vme_resource *resource, = void *buf, size_t count, ssize_t vme_master_write(struct vme_resource *resource, void *buf, size_t = count, loff_t offset); unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int ma= sk, unsigned int compare, unsigned int swap, loff_t offset); -int vme_master_mmap(struct vme_resource *resource, struct vm_area_struct *= vma); +int vme_master_mmap_prepare(struct vme_resource *resource, struct vm_area_= desc *desc); void vme_master_free(struct vme_resource *resource); =20 struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route); diff --git a/drivers/staging/vme_user/vme_user.c b/drivers/staging/vme_user= /vme_user.c index d95dd7d9190a..11e25c2f6b0a 100644 --- a/drivers/staging/vme_user/vme_user.c +++ b/drivers/staging/vme_user/vme_user.c @@ -446,24 +446,14 @@ static void vme_user_vm_close(struct vm_area_struct *= vma) kfree(vma_priv); } =20 -static const struct vm_operations_struct vme_user_vm_ops =3D { - .open =3D vme_user_vm_open, - .close =3D vme_user_vm_close, -}; - -static int vme_user_master_mmap(unsigned int minor, struct vm_area_struct = *vma) +static int vme_user_vm_mapped(unsigned long start, unsigned long end, pgof= f_t pgoff, + const struct file *file, void **vm_private_data) { - int err; + const unsigned int minor =3D iminor(file_inode(file)); struct vme_user_vma_priv *vma_priv; =20 mutex_lock(&image[minor].mutex); =20 - err =3D vme_master_mmap(image[minor].resource, vma); - if (err) { - mutex_unlock(&image[minor].mutex); - return err; - } - vma_priv =3D kmalloc_obj(*vma_priv); if (!vma_priv) { mutex_unlock(&image[minor].mutex); @@ -472,22 +462,41 @@ static int vme_user_master_mmap(unsigned int minor, s= truct vm_area_struct *vma) =20 vma_priv->minor =3D minor; refcount_set(&vma_priv->refcnt, 1); - vma->vm_ops =3D &vme_user_vm_ops; - vma->vm_private_data =3D vma_priv; - + *vm_private_data =3D vma_priv; image[minor].mmap_count++; =20 mutex_unlock(&image[minor].mutex); - return 0; } =20 -static int vme_user_mmap(struct file *file, struct vm_area_struct *vma) +static const struct vm_operations_struct vme_user_vm_ops =3D { + .mapped =3D vme_user_vm_mapped, + .open =3D vme_user_vm_open, + .close =3D vme_user_vm_close, +}; + +static int vme_user_master_mmap_prepare(unsigned int minor, + struct vm_area_desc *desc) +{ + int err; + + mutex_lock(&image[minor].mutex); + + err =3D vme_master_mmap_prepare(image[minor].resource, desc); + if (!err) + desc->vm_ops =3D &vme_user_vm_ops; + + mutex_unlock(&image[minor].mutex); + return err; +} + +static int vme_user_mmap_prepare(struct vm_area_desc *desc) { - unsigned int minor =3D iminor(file_inode(file)); + const struct file *file =3D desc->file; + const unsigned int minor =3D iminor(file_inode(file)); =20 if (type[minor] =3D=3D MASTER_MINOR) - return vme_user_master_mmap(minor, vma); + return vme_user_master_mmap_prepare(minor, desc); =20 return -ENODEV; } @@ -498,7 +507,7 @@ static const struct file_operations vme_user_fops =3D { .llseek =3D vme_user_llseek, .unlocked_ioctl =3D vme_user_unlocked_ioctl, .compat_ioctl =3D compat_ptr_ioctl, - .mmap =3D vme_user_mmap, + .mmap_prepare =3D vme_user_mmap_prepare, }; =20 static int vme_user_match(struct vme_dev *vdev) --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76DF03D7D9F; Fri, 20 Mar 2026 22:40:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046454; cv=none; b=mAl6AO9BJy+q9J0Y5WAt8ngvKcYMBGbhR66CEqul6NEm3SIjvptA/BEZZXmnBOw462PnMyxxSdY1MK5r6Dp8z4xx7zDz9IdhACVrI/4ZOR+d35UTmpZfIZmseYoVOjI+Yjxeu70CR8L6QPpJkfjuXbyjdS76vW+FfkK/y4pFdDE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046454; c=relaxed/simple; bh=fRD05uAyOWBqNhdag2475Dgc8A9zXK7k9oX0V7v52Io=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XWWZIXu2B/2Q2WcTo4HsMAndsgdZMYd14zSsEneZ6LE7RanFvYWu3wIoIFM4UcV8UA3hzb6+AP4bZ28KpXPuiYY8ffZtoC087A0RuWcDUfP4kWhBPVVAmzsPZF1NSe9P2rR7/aC5VvgHh4xyjoI0ajFA+SL1fgvOGr2PJRkgPeg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BGuUE9a4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BGuUE9a4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7CFD4C2BC87; Fri, 20 Mar 2026 22:40:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046454; bh=fRD05uAyOWBqNhdag2475Dgc8A9zXK7k9oX0V7v52Io=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BGuUE9a4c2hZHiqHujn0BUmFS7EklH8dhxhHAHfiYxu7U0JEOD0eUVwF2CD3zpU3B sfPyqFh3UoHDr0a7ssNkZeCHZwcJJwulK6/N5tnUhUpRuJJKs0uIa/ELG2wTrPDYTN IvFAfTOz9iVUM8RUdZsz+8XE+UPFPLCUpG4adN8Itfu+IyN/4h6f75HXhbMTYD9gT+ j2FlwRuikF7v0mMHp1k+0I7Uizqk5Rsfc/GfB8PdlB7MAWEO/RvlGtLmMgBedYYE+L 2KFlFDq63Q+BbzKGkAvt/n0COHMOR9R+oy/Kh0S4aw6gBAKwkgfSA+YpVy/li5v80z JGpbmw+QzEAuQ== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 17/21] mm: allow handling of stacked mmap_prepare hooks in more drivers Date: Fri, 20 Mar 2026 22:39:43 +0000 Message-ID: <24aac3019dd34740e788d169fccbe3c62781e648.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" While the conversion of mmap hooks to mmap_prepare is underway, we will encounter situations where mmap hooks need to invoke nested mmap_prepare hooks. The nesting of mmap hooks is termed 'stacking'. In order to flexibly facilitate the conversion of custom mmap hooks in drivers which stack, we must split up the existing __compat_vma_mmap() function into two separate functions: * compat_set_desc_from_vma() - This allows the setting of a vm_area_desc object's fields to the relevant fields of a VMA. * __compat_vma_mmap() - Once an mmap_prepare hook has been executed upon a vm_area_desc object, this function performs any mmap actions specified by the mmap_prepare hook and then invokes its vm_ops->mapped() hook if any were specified. In ordinary cases, where a file's f_op->mmap_prepare() hook simply needs to be invoked in a stacked mmap() hook, compat_vma_mmap() can be used. However some drivers define their own nested hooks, which are invoked in turn by another hook. A concrete example is vmbus_channel->mmap_ring_buffer(), which is invoked in turn by bin_attribute->mmap(): vmbus_channel->mmap_ring_buffer() has a signature of: int (*mmap_ring_buffer)(struct vmbus_channel *channel, struct vm_area_struct *vma); And bin_attribute->mmap() has a signature of: int (*mmap)(struct file *, struct kobject *, const struct bin_attribute *attr, struct vm_area_struct *vma); And so compat_vma_mmap() cannot be used here for incremental conversion of hooks from mmap() to mmap_prepare(). There are many such instances like this, where conversion to mmap_prepare would otherwise cascade to a huge change set due to nesting of this kind. The changes in this patch mean we could now instead convert vmbus_channel->mmap_ring_buffer() to vmbus_channel->mmap_prepare_ring_buffer(), and implement something like: struct vm_area_desc desc; int err; compat_set_desc_from_vma(&desc, file, vma); err =3D channel->mmap_prepare_ring_buffer(channel, &desc); if (err) return err; return __compat_vma_mmap(&desc, vma); Allowing us to incrementally update this logic, and other logic like it. Unfortunately, as part of this change, we need to be able to flexibly assign to the VMA descriptor, so have to remove some of the const declarations within the structure. Also update the VMA tests to reflect the changes. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- include/linux/fs.h | 3 + include/linux/mm_types.h | 4 +- mm/util.c | 119 +++++++++++++++++++++++--------- mm/vma.h | 2 +- tools/testing/vma/include/dup.h | 68 +++++++++++------- 5 files changed, 136 insertions(+), 60 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index c390f5c667e3..0bdccfa70b44 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2058,6 +2058,9 @@ static inline bool can_mmap_file(struct file *file) return true; } =20 +void compat_set_desc_from_vma(struct vm_area_desc *desc, const struct file= *file, + const struct vm_area_struct *vma); +int __compat_vma_mmap(struct vm_area_desc *desc, struct vm_area_struct *vm= a); int compat_vma_mmap(struct file *file, struct vm_area_struct *vma); int __vma_check_mmap_hook(struct vm_area_struct *vma); =20 diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 174286f9ecf0..d60eefde1db8 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -891,8 +891,8 @@ static __always_inline bool vma_flags_empty(const vma_f= lags_t *flags) */ struct vm_area_desc { /* Immutable state. */ - const struct mm_struct *const mm; - struct file *const file; /* May vary from vm_file in stacked callers. */ + struct mm_struct *mm; + struct file *file; /* May vary from vm_file in stacked callers. */ unsigned long start; unsigned long end; =20 diff --git a/mm/util.c b/mm/util.c index a19f062b84dc..5ae20876ef2c 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1163,38 +1163,78 @@ void flush_dcache_folio(struct folio *folio) EXPORT_SYMBOL(flush_dcache_folio); #endif =20 -static int __compat_vma_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct vm_area_desc desc =3D { - .mm =3D vma->vm_mm, - .file =3D file, - .start =3D vma->vm_start, - .end =3D vma->vm_end, - - .pgoff =3D vma->vm_pgoff, - .vm_file =3D vma->vm_file, - .vma_flags =3D vma->flags, - .page_prot =3D vma->vm_page_prot, - - .action.type =3D MMAP_NOTHING, /* Default */ - }; - struct mmap_action *action =3D &desc.action; - int err; +/** + * compat_set_desc_from_vma() - assigns VMA descriptor @desc fields from a= VMA. + * @desc: A VMA descriptor whose fields need to be set. + * @file: The file object describing the file being mmap()'d. + * @vma: The VMA whose fields we wish to assign to @desc. + * + * This is a compatibility function to allow an mmap() hook to call + * mmap_prepare() hooks when drivers nest these. This function specifically + * allows the construction of a vm_area_desc value, @desc, from a VMA @vma= for + * the purposes of doing this. + * + * Once the conversion of drivers is complete this function will no longer= be + * required and will be removed. + */ +void compat_set_desc_from_vma(struct vm_area_desc *desc, + const struct file *file, + const struct vm_area_struct *vma) +{ + memset(desc, 0, sizeof(*desc)); =20 - err =3D vfs_mmap_prepare(file, &desc); - if (err) - return err; + desc->mm =3D vma->vm_mm; + desc->file =3D (struct file *)file; + desc->start =3D vma->vm_start; + desc->end =3D vma->vm_end; =20 - err =3D mmap_action_prepare(&desc); - if (err) - return err; + desc->pgoff =3D vma->vm_pgoff; + desc->vm_file =3D vma->vm_file; + desc->vma_flags =3D vma->flags; + desc->page_prot =3D vma->vm_page_prot; =20 - /* being invoked from .mmmap means we don't have to enforce this. */ - action->hide_from_rmap_until_complete =3D false; + /* Default. */ + desc->action.type =3D MMAP_NOTHING; +} +EXPORT_SYMBOL(compat_set_desc_from_vma); + +/** + * __compat_vma_mmap() - Similar to compat_vma_mmap(), only it allows + * flexibility as to how the mmap_prepare callback is invoked, which is us= eful + * for drivers which invoke nested mmap_prepare callbacks in an mmap() hoo= k. + * @desc: A VMA descriptor upon which an mmap_prepare() hook has already b= een + * executed. + * @vma: The VMA to which @desc should be applied. + * + * The function assumes that you have obtained a VMA descriptor @desc from + * compat_set_desc_from_vma(), and already executed the mmap_prepare() hoo= k upon + * it. + * + * It then performs any specified mmap actions, and invokes the vm_ops->ma= pped() + * hook if one is present. + * + * See the description of compat_vma_mmap() for more details. + * + * Once the conversion of drivers is complete this function will no longer= be + * required and will be removed. + * + * Returns: 0 on success or error. + */ +int __compat_vma_mmap(struct vm_area_desc *desc, + struct vm_area_struct *vma) +{ + int err; =20 - set_vma_from_desc(vma, &desc); - return mmap_action_complete(vma, action); + /* Perform any preparatory tasks for mmap action. */ + err =3D mmap_action_prepare(desc); + if (err) + return err; + /* Update the VMA from the descriptor. */ + compat_set_vma_from_desc(vma, desc); + /* Complete any specified mmap actions. */ + return mmap_action_complete(vma, &desc->action); } +EXPORT_SYMBOL(__compat_vma_mmap); =20 /** * compat_vma_mmap() - Apply the file's .mmap_prepare() hook to an @@ -1203,10 +1243,10 @@ static int __compat_vma_mmap(struct file *file, str= uct vm_area_struct *vma) * @vma: The VMA to apply the .mmap_prepare() hook to. * * Ordinarily, .mmap_prepare() is invoked directly upon mmap(). However, c= ertain - * stacked filesystems invoke a nested mmap hook of an underlying file. + * stacked drivers invoke a nested mmap hook of an underlying file. * - * Until all filesystems are converted to use .mmap_prepare(), we must be - * conservative and continue to invoke these stacked filesystems using the + * Until all drivers are converted to use .mmap_prepare(), we must be + * conservative and continue to invoke these stacked drivers using the * deprecated .mmap() hook. * * However we have a problem if the underlying file system possesses an @@ -1217,14 +1257,27 @@ static int __compat_vma_mmap(struct file *file, str= uct vm_area_struct *vma) * establishes a struct vm_area_desc descriptor, passes to the underlying * .mmap_prepare() hook and applies any changes performed by it. * - * Once the conversion of filesystems is complete this function will no lo= nger - * be required and will be removed. + * Once the conversion of drivers is complete this function will no longer= be + * required and will be removed. * * Returns: 0 on success or error. */ int compat_vma_mmap(struct file *file, struct vm_area_struct *vma) { - return __compat_vma_mmap(file, vma); + struct vm_area_desc desc; + struct mmap_action *action; + int err; + + compat_set_desc_from_vma(&desc, file, vma); + err =3D vfs_mmap_prepare(file, &desc); + if (err) + return err; + action =3D &desc.action; + + /* being invoked from .mmmap means we don't have to enforce this. */ + action->hide_from_rmap_until_complete =3D false; + + return __compat_vma_mmap(&desc, vma); } EXPORT_SYMBOL(compat_vma_mmap); =20 diff --git a/mm/vma.h b/mm/vma.h index adc18f7dd9f1..a76046c39b14 100644 --- a/mm/vma.h +++ b/mm/vma.h @@ -300,7 +300,7 @@ static inline int vma_iter_store_gfp(struct vma_iterato= r *vmi, * f_op->mmap() but which might have an underlying file system which imple= ments * f_op->mmap_prepare(). */ -static inline void set_vma_from_desc(struct vm_area_struct *vma, +static inline void compat_set_vma_from_desc(struct vm_area_struct *vma, struct vm_area_desc *desc) { /* diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index a0c2379bd42b..f5f7c45f1808 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -519,8 +519,8 @@ enum vma_operation { */ struct vm_area_desc { /* Immutable state. */ - const struct mm_struct *const mm; - struct file *const file; /* May vary from vm_file in stacked callers. */ + struct mm_struct *mm; + struct file *file; /* May vary from vm_file in stacked callers. */ unsigned long start; unsigned long end; =20 @@ -1274,50 +1274,70 @@ static inline void vma_set_anonymous(struct vm_area= _struct *vma) } =20 /* Declared in vma.h. */ -static inline void set_vma_from_desc(struct vm_area_struct *vma, +static inline void compat_set_vma_from_desc(struct vm_area_struct *vma, struct vm_area_desc *desc); =20 -static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc = *desc) +static inline void compat_set_desc_from_vma(struct vm_area_desc *desc, + const struct file *file, + const struct vm_area_struct *vma) { - return file->f_op->mmap_prepare(desc); + memset(desc, 0, sizeof(*desc)); + + desc->mm =3D vma->vm_mm; + desc->file =3D (struct file *)file; + desc->start =3D vma->vm_start; + desc->end =3D vma->vm_end; + + desc->pgoff =3D vma->vm_pgoff; + desc->vm_file =3D vma->vm_file; + desc->vma_flags =3D vma->flags; + desc->page_prot =3D vma->vm_page_prot; + + /* Default. */ + desc->action.type =3D MMAP_NOTHING; } =20 -static inline unsigned long vma_pages(struct vm_area_struct *vma) +static inline unsigned long vma_pages(const struct vm_area_struct *vma) { return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; } =20 -static inline int compat_vma_mmap(struct file *file, struct vm_area_struct= *vma) +static inline int vfs_mmap_prepare(struct file *file, struct vm_area_desc = *desc) { - struct vm_area_desc desc =3D { - .mm =3D vma->vm_mm, - .file =3D file, - .start =3D vma->vm_start, - .end =3D vma->vm_end, - - .pgoff =3D vma->vm_pgoff, - .vm_file =3D vma->vm_file, - .vma_flags =3D vma->flags, - .page_prot =3D vma->vm_page_prot, + return file->f_op->mmap_prepare(desc); +} =20 - .action.type =3D MMAP_NOTHING, /* Default */ - }; - struct mmap_action *action =3D &desc.action; +static inline int __compat_vma_mmap(struct vm_area_desc *desc, + struct vm_area_struct *vma) +{ int err; =20 - err =3D vfs_mmap_prepare(file, &desc); + /* Perform any preparatory tasks for mmap action. */ + err =3D mmap_action_prepare(desc); if (err) return err; + /* Update the VMA from the descriptor. */ + compat_set_vma_from_desc(vma, desc); + /* Complete any specified mmap actions. */ + return mmap_action_complete(vma, &desc->action); +} =20 - err =3D mmap_action_prepare(&desc); +static inline int compat_vma_mmap(struct file *file, struct vm_area_struct= *vma) +{ + struct vm_area_desc desc; + struct mmap_action *action; + int err; + + compat_set_desc_from_vma(&desc, file, vma); + err =3D vfs_mmap_prepare(file, &desc); if (err) return err; + action =3D &desc.action; =20 /* being invoked from .mmmap means we don't have to enforce this. */ action->hide_from_rmap_until_complete =3D false; =20 - set_vma_from_desc(vma, &desc); - return mmap_action_complete(vma, action); + return __compat_vma_mmap(&desc, vma); } =20 static inline void vma_iter_init(struct vma_iterator *vmi, --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24E023CAE87; Fri, 20 Mar 2026 22:40:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046457; cv=none; b=bZY1UCjx9pnD+H7ZNe8KWEmkuojIuLPxj96OwoQiSQKaSvIuIk3+t0FhTdFwN18qAtHdAflDplen90fCMbQS+89LkTL1Wm1pL25Q5TpIhQzabnjyeAxDQ2+JSrAbTQv+/EKix8U2sa31Om2s0SY+3vwtAIueNVewbop9NF5cVbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046457; c=relaxed/simple; bh=xqeFdev8haZYqVKb9RyAQUT5x4QpuIREk0dFqk3m3oA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YxpkC7q2sr+/w8ffEQzYOqNtGgmM5JIQj8tyhyavol1ofSL42GSrSNE27GuJIPGz/l0G/Spzy5KWh0OnuNjL5y+A8jzXptw2MuL0PxDCRL3YJwenPgh7Hq/VB0XiU2zps8QbXTXbw8av6Dfl4l2N7/S7kkrXV0EVn25xpFHcX98= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ta1BWmG+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ta1BWmG+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 42EBDC2BCB3; Fri, 20 Mar 2026 22:40:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046456; bh=xqeFdev8haZYqVKb9RyAQUT5x4QpuIREk0dFqk3m3oA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ta1BWmG+lKEvULUrkIqxcRrEauWLsPXM1vw43UOroW5hCg4QdgHQBNdQ6lzuTH5S5 DkWLqekfny+lspMP5VejVzvED04z2eHKToE6Rst7ECjJniAb8+zQKeFYZ1eJz77Idm U42YuzuNtW+ULPShZpun08YIPI0Jt/5zTpLV0cwrmkGcSSIfW9R5R9apFNiqUqrLVl XQPbMYRAwOp09T1kmPM6ucN6Nn6t50F7LM+mHsj+e20Uqv1tWX5lSbYyyVLdVjxSHv bhJ88OMstEOxhd6UjedfwuzadWGPmjtL96PIa2yfgf63ZyMDdOgOrBMsFUvVRA3K3X 5P4jhUQTq4VaQ== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 18/21] drivers: hv: vmbus: replace deprecated mmap hook with mmap_prepare Date: Fri, 20 Mar 2026 22:39:44 +0000 Message-ID: <05467cb62267d750e5c770147517d4df0246cda6.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update the vmbus driver to use its successor, mmap_prepare. This updates all callbacks which referenced the function pointer hv_mmap_ring_buffer to instead reference hv_mmap_prepare_ring_buffer, utilising the newly introduced compat_set_desc_from_vma() and __compat_vma_mmap() to be able to implement this change. The UIO HV generic driver is the only user of hv_create_ring_sysfs(), which is the only function which references vmbus_channel->mmap_prepare_ring_buffer which, in turn, is the only external interface to hv_mmap_prepare_ring_buffer. This patch therefore updates this caller to use mmap_prepare instead, which also previously used vm_iomap_memory(), so this change replaces it with its mmap_prepare equivalent, mmap_action_simple_ioremap(). Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/hv/hyperv_vmbus.h | 4 ++-- drivers/hv/vmbus_drv.c | 31 +++++++++++++++++++------------ drivers/uio/uio_hv_generic.c | 11 ++++++----- include/linux/hyperv.h | 4 ++-- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 7bd8f8486e85..31f576464f18 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -545,8 +545,8 @@ static inline int hv_debug_add_dev_dir(struct hv_device= *dev) =20 /* Create and remove sysfs entry for memory mapped ring buffers for a chan= nel */ int hv_create_ring_sysfs(struct vmbus_channel *channel, - int (*hv_mmap_ring_buffer)(struct vmbus_channel *channel, - struct vm_area_struct *vma)); + int (*hv_mmap_prepare_ring_buffer)(struct vmbus_channel *channel, + struct vm_area_desc *desc)); int hv_remove_ring_sysfs(struct vmbus_channel *channel); =20 #endif /* _HYPERV_VMBUS_H */ diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index bc4fc1951ae1..45625487ba36 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1951,12 +1951,19 @@ static int hv_mmap_ring_buffer_wrapper(struct file = *filp, struct kobject *kobj, struct vm_area_struct *vma) { struct vmbus_channel *channel =3D container_of(kobj, struct vmbus_channel= , kobj); + struct vm_area_desc desc; + int err; =20 /* - * hv_(create|remove)_ring_sysfs implementation ensures that mmap_ring_bu= ffer - * is not NULL. + * hv_(create|remove)_ring_sysfs implementation ensures that + * mmap_prepare_ring_buffer is not NULL. */ - return channel->mmap_ring_buffer(channel, vma); + compat_set_desc_from_vma(&desc, filp, vma); + err =3D channel->mmap_prepare_ring_buffer(channel, &desc); + if (err) + return err; + + return __compat_vma_mmap(&desc, vma); } =20 static struct bin_attribute chan_attr_ring_buffer =3D { @@ -2048,13 +2055,13 @@ static const struct kobj_type vmbus_chan_ktype =3D { /** * hv_create_ring_sysfs() - create "ring" sysfs entry corresponding to rin= g buffers for a channel. * @channel: Pointer to vmbus_channel structure - * @hv_mmap_ring_buffer: function pointer for initializing the function to= be called on mmap of + * @hv_mmap_prepare_ring_buffer: function pointer for initializing the fun= ction to be called on mmap * channel's "ring" sysfs node, which is for the rin= g buffer of that channel. * Function pointer is of below type: - * int (*hv_mmap_ring_buffer)(struct vmbus_channel *= channel, - * struct vm_area_struct = *vma)) - * This has a pointer to the channel and a pointer t= o vm_area_struct, - * used for mmap, as arguments. + * int (*hv_mmap_prepare_ring_buffer)(struct vmbus_c= hannel *channel, + * struct vm_area= _desc *desc)) + * This has a pointer to the channel and a pointer t= o vm_area_desc, + * used for mmap_prepare, as arguments. * * Sysfs node for ring buffer of a channel is created along with other fie= lds, however its * visibility is disabled by default. Sysfs creation needs to be controlle= d when the use-case @@ -2071,12 +2078,12 @@ static const struct kobj_type vmbus_chan_ktype =3D { * Returns 0 on success or error code on failure. */ int hv_create_ring_sysfs(struct vmbus_channel *channel, - int (*hv_mmap_ring_buffer)(struct vmbus_channel *channel, - struct vm_area_struct *vma)) + int (*hv_mmap_prepare_ring_buffer)(struct vmbus_channel *channel, + struct vm_area_desc *desc)) { struct kobject *kobj =3D &channel->kobj; =20 - channel->mmap_ring_buffer =3D hv_mmap_ring_buffer; + channel->mmap_prepare_ring_buffer =3D hv_mmap_prepare_ring_buffer; channel->ring_sysfs_visible =3D true; =20 return sysfs_update_group(kobj, &vmbus_chan_group); @@ -2098,7 +2105,7 @@ int hv_remove_ring_sysfs(struct vmbus_channel *channe= l) =20 channel->ring_sysfs_visible =3D false; ret =3D sysfs_update_group(kobj, &vmbus_chan_group); - channel->mmap_ring_buffer =3D NULL; + channel->mmap_prepare_ring_buffer =3D NULL; return ret; } EXPORT_SYMBOL_GPL(hv_remove_ring_sysfs); diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c index 3f8e2e27697f..29ec2d15ada8 100644 --- a/drivers/uio/uio_hv_generic.c +++ b/drivers/uio/uio_hv_generic.c @@ -154,15 +154,16 @@ static void hv_uio_rescind(struct vmbus_channel *chan= nel) * The ring buffer is allocated as contiguous memory by vmbus_open */ static int -hv_uio_ring_mmap(struct vmbus_channel *channel, struct vm_area_struct *vma) +hv_uio_ring_mmap_prepare(struct vmbus_channel *channel, struct vm_area_des= c *desc) { void *ring_buffer =3D page_address(channel->ringbuffer_page); =20 if (channel->state !=3D CHANNEL_OPENED_STATE) return -ENODEV; =20 - return vm_iomap_memory(vma, virt_to_phys(ring_buffer), - channel->ringbuffer_pagecount << PAGE_SHIFT); + mmap_action_simple_ioremap(desc, virt_to_phys(ring_buffer), + channel->ringbuffer_pagecount << PAGE_SHIFT); + return 0; } =20 /* Callback from VMBUS subsystem when new channel created. */ @@ -183,7 +184,7 @@ hv_uio_new_channel(struct vmbus_channel *new_sc) } =20 set_channel_read_mode(new_sc, HV_CALL_ISR); - ret =3D hv_create_ring_sysfs(new_sc, hv_uio_ring_mmap); + ret =3D hv_create_ring_sysfs(new_sc, hv_uio_ring_mmap_prepare); if (ret) { dev_err(device, "sysfs create ring bin file failed; %d\n", ret); vmbus_close(new_sc); @@ -366,7 +367,7 @@ hv_uio_probe(struct hv_device *dev, * or decoupled from uio_hv_generic probe. Userspace programs can make us= e of inotify * APIs to make sure that ring is created. */ - hv_create_ring_sysfs(channel, hv_uio_ring_mmap); + hv_create_ring_sysfs(channel, hv_uio_ring_mmap_prepare); =20 hv_set_drvdata(dev, pdata); =20 diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index dfc516c1c719..3a721b1853a4 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1015,8 +1015,8 @@ struct vmbus_channel { /* The max size of a packet on this channel */ u32 max_pkt_size; =20 - /* function to mmap ring buffer memory to the channel's sysfs ring attrib= ute */ - int (*mmap_ring_buffer)(struct vmbus_channel *channel, struct vm_area_str= uct *vma); + /* function to mmap_prepare ring buffer memory to the channel's sysfs rin= g attribute */ + int (*mmap_prepare_ring_buffer)(struct vmbus_channel *channel, struct vm_= area_desc *desc); =20 /* boolean to control visibility of sysfs for ring buffer */ bool ring_sysfs_visible; --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10AC23CCFAB; Fri, 20 Mar 2026 22:40:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046460; cv=none; b=js0ickGltBdWu2patEHhNAWLtjLWzBIzhfcb/GIGSkFiZTBnmjf7Bx+V7U0rniJsJYCCVBbF/jPx7+FhxIExzmBONjfHPhQseMsUJf5Ox4U6XnymLZ/VGK/xfdGp9+UAeZmjvyUnZb9tx36sCHE//3bl9N25GjNTWTYKqmYHmwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046460; c=relaxed/simple; bh=RbmL9EYUSm+5mPpVtsO49vrMj2KZeRXZE1ebFppsMFI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bmgHFgk6iqOCRysydshzQM9+K2kEnM+hfpqlTjI/Eeb35hsXoKFpCRUXzmzN/Ra1v/MqZLLqcucFfvMYxGKgqjacBZK51PZ1L3bfKIPSxUjKQ8SFznh0HFmsIuMXK/LGScfdCA0GtY8vuZPQU10UdWyHMN2oYEYQeDmKL6hHksk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E9KiFrke; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="E9KiFrke" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E5D17C2BC9E; Fri, 20 Mar 2026 22:40:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046459; bh=RbmL9EYUSm+5mPpVtsO49vrMj2KZeRXZE1ebFppsMFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E9KiFrke6/pWAK9+oFWd7P9eAYjZDzF870vM+tWk724Ryw4Olx0yNweK87TZ70mz1 WyOmWBl28Snml/0ZjgQ3MTDeN7jmfaylo1ES4KeSCQKcJqnD/JoyZdvv5Vyam7SA4s Kmz+ogGB5QCjFjeOkqt4UUNDpHvbUTEmg+OONpPr1XQpNBCfI24BXG0ah+cLWMz7xi BugY6CF2cXfB3GwMfbyce9XHA+WMXsW/t7kVNcyfonju4ZoR40+4/+W3aL/iNiDTRp 38FjMrd8mvmNwW7IkW7tGGMljFTpkO6nTKfpE/nmlF4xR3zSVTWbJd17n5Dr64LmUw Lmt7Jo3FLLiSg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 19/21] uio: replace deprecated mmap hook with mmap_prepare in uio_info Date: Fri, 20 Mar 2026 22:39:45 +0000 Message-ID: <157583e4477705b496896c7acd4ac88a937b8fa6.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The f_op->mmap interface is deprecated, so update uio_info to use its successor, mmap_prepare. Therefore, replace the uio_info->mmap hook with a new uio_info->mmap_prepare hook, and update its one user, target_core_user, to both specify this new mmap_prepare hook and also to use the new vm_ops->mapped() hook to continue to maintain a correct udev->kref refcount. Then update uio_mmap() to utilise the mmap_prepare compatibility layer to invoke this callback from the uio mmap invocation. Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- drivers/target/target_core_user.c | 26 ++++++++++++++++++-------- drivers/uio/uio.c | 10 ++++++++-- include/linux/uio_driver.h | 4 ++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core= _user.c index af95531ddd35..edc2afd5f4ee 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1860,6 +1860,17 @@ static struct page *tcmu_try_get_data_page(struct tc= mu_dev *udev, uint32_t dpi) return NULL; } =20 +static int tcmu_vma_mapped(unsigned long start, unsigned long end, pgoff_t= pgoff, + const struct file *file, void **vm_private_data) +{ + struct tcmu_dev *udev =3D *vm_private_data; + + pr_debug("vma_mapped\n"); + + kref_get(&udev->kref); + return 0; +} + static void tcmu_vma_open(struct vm_area_struct *vma) { struct tcmu_dev *udev =3D vma->vm_private_data; @@ -1919,26 +1930,25 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *v= mf) } =20 static const struct vm_operations_struct tcmu_vm_ops =3D { + .mapped =3D tcmu_vma_mapped, .open =3D tcmu_vma_open, .close =3D tcmu_vma_close, .fault =3D tcmu_vma_fault, }; =20 -static int tcmu_mmap(struct uio_info *info, struct vm_area_struct *vma) +static int tcmu_mmap_prepare(struct uio_info *info, struct vm_area_desc *d= esc) { struct tcmu_dev *udev =3D container_of(info, struct tcmu_dev, uio_info); =20 - vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_ops =3D &tcmu_vm_ops; + vma_desc_set_flags(desc, VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT); + desc->vm_ops =3D &tcmu_vm_ops; =20 - vma->vm_private_data =3D udev; + desc->private_data =3D udev; =20 /* Ensure the mmap is exactly the right size */ - if (vma_pages(vma) !=3D udev->mmap_pages) + if (vma_desc_pages(desc) !=3D udev->mmap_pages) return -EINVAL; =20 - tcmu_vma_open(vma); - return 0; } =20 @@ -2253,7 +2263,7 @@ static int tcmu_configure_device(struct se_device *de= v) info->irqcontrol =3D tcmu_irqcontrol; info->irq =3D UIO_IRQ_CUSTOM; =20 - info->mmap =3D tcmu_mmap; + info->mmap_prepare =3D tcmu_mmap_prepare; info->open =3D tcmu_open; info->release =3D tcmu_release; =20 diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 5a4998e2caf8..1e4ade78ed84 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -850,8 +850,14 @@ static int uio_mmap(struct file *filep, struct vm_area= _struct *vma) goto out; } =20 - if (idev->info->mmap) { - ret =3D idev->info->mmap(idev->info, vma); + if (idev->info->mmap_prepare) { + struct vm_area_desc desc; + + compat_set_desc_from_vma(&desc, filep, vma); + ret =3D idev->info->mmap_prepare(idev->info, &desc); + if (ret) + goto out; + ret =3D __compat_vma_mmap(&desc, vma); goto out; } =20 diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index 334641e20fb1..02eaac47ac44 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -97,7 +97,7 @@ struct uio_device { * @irq_flags: flags for request_irq() * @priv: optional private data * @handler: the device's irq handler - * @mmap: mmap operation for this uio device + * @mmap_prepare: mmap_prepare operation for this uio device * @open: open operation for this uio device * @release: release operation for this uio device * @irqcontrol: disable/enable irqs when 0/1 is written to /dev/uioX @@ -112,7 +112,7 @@ struct uio_info { unsigned long irq_flags; void *priv; irqreturn_t (*handler)(int irq, struct uio_info *dev_info); - int (*mmap)(struct uio_info *info, struct vm_area_struct *vma); + int (*mmap_prepare)(struct uio_info *info, struct vm_area_desc *desc); int (*open)(struct uio_info *info, struct inode *inode); int (*release)(struct uio_info *info, struct inode *inode); int (*irqcontrol)(struct uio_info *info, s32 irq_on); --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 754063F9F4C; Fri, 20 Mar 2026 22:41:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046462; cv=none; b=ljmIg6QXoA/gylFe3Clk3ICXPk8uevCHZuEhZSFK/dWeRzxQxgHvNwQAUpHI+1qPr7JyQfDmQRGlGY8XgO4RQPrpwltG9PraZnXZiPtiaiGLNqIZN4ZlrtlsBaZmQmYw9pQYfI6kr224LWeDzYy9/c3tXAPGk64rJ5FAlNyCdTc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046462; c=relaxed/simple; bh=PC8UT5FrOE7raPDJyXK5xkA7GADphHu1Lkj1dxP3k+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tHBNNY4rC8NHtulzHnJX4YyeqaJWWBN421D5Sn4T1z8903Yk9WpVGu2ckwhVSO0uFpTSw2hj7eCxcmcIA4/Bqs5XZ39gSfqXxf7NK4iy0eNWHAo8otr/k1e/YlbOMVv5M575hMQeKw5efnh62+Aw6tc3C05kY6ipOA2lFDE6f8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LB/UaFWL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LB/UaFWL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AEFDFC2BCB1; Fri, 20 Mar 2026 22:41:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046462; bh=PC8UT5FrOE7raPDJyXK5xkA7GADphHu1Lkj1dxP3k+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LB/UaFWL0AckuWEpPx7qUcJo2w+95GJiPatq+AYNCm6c8XPlZnnCIZJXl1wxJFezK 3zxcUT7cyOGO99x76SslEh2hUby34dCvo8MvuZWkr5lcIJ3v/5wVebGpGDDRKm7o7X kPRmOCx1iZ70VUf6k3bHoideWAt8MWrhaAi4MHAeF4s8dUupO6LPLC7/3pdRRcmMBw y0xIz1koeyTRyvVzEhda9hxPIet5JrGAN+B87pO/xCRFsFwMX5rkzJA9jAX8Tc+m1q 8/DTtyvunjD3f5i+k8Y9xDzFlwwFJKw3EcUHLvXdfjsYFA4H2o66RqUp08jopTGG2k wBawkzh53K7Dg== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 20/21] mm: add mmap_action_map_kernel_pages[_full]() Date: Fri, 20 Mar 2026 22:39:46 +0000 Message-ID: <926ac961690d856e67ec847bee2370ab3c6b9046.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A user can invoke mmap_action_map_kernel_pages() to specify that the mapping should map kernel pages starting from desc->start of a specified number of pages specified in an array. In order to implement this, adjust mmap_action_prepare() to be able to return an error code, as it makes sense to assert that the specified parameters are valid as quickly as possible as well as updating the VMA flags to include VMA_MIXEDMAP_BIT as necessary. This provides an mmap_prepare equivalent of vm_insert_pages(). We additionally update the existing vm_insert_pages() code to use range_in_vma() and add a new range_in_vma_desc() helper function for the mmap_prepare case, sharing the code between the two in range_is_subset(). We add both mmap_action_map_kernel_pages() and mmap_action_map_kernel_pages_full() to allow for both partial and full VMA mappings. We update the documentation to reflect the new features. Finally, we update the VMA tests accordingly to reflect the changes. Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- Documentation/filesystems/mmap_prepare.rst | 8 ++ include/linux/mm.h | 95 +++++++++++++++++++++- include/linux/mm_types.h | 7 ++ mm/memory.c | 42 +++++++++- mm/util.c | 7 ++ tools/testing/vma/include/dup.h | 7 ++ 6 files changed, 160 insertions(+), 6 deletions(-) diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/fil= esystems/mmap_prepare.rst index 14bb057be564..82c99c95ad85 100644 --- a/Documentation/filesystems/mmap_prepare.rst +++ b/Documentation/filesystems/mmap_prepare.rst @@ -156,5 +156,13 @@ pointer. These are: * mmap_action_simple_ioremap() - Sets up an I/O remap from a specified physical address and over a specified length. =20 +* mmap_action_map_kernel_pages() - Maps a specified array of `struct page` + pointers in the VMA from a specific offset. + +* mmap_action_map_kernel_pages_full() - Maps a specified array of `struct + page` pointers over the entire VMA. The caller must ensure there are + sufficient entries in the page array to cover the entire range of the + described VMA. + **NOTE:** The ``action`` field should never normally be manipulated direct= ly, rather you ought to use one of these helpers. diff --git a/include/linux/mm.h b/include/linux/mm.h index df8fa6e6402b..6f0a3edb24e1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2912,7 +2912,7 @@ static inline bool folio_maybe_mapped_shared(struct f= olio *folio) * The caller must add any reference (e.g., from folio_try_get()) it might= be * holding itself to the result. * - * Returns the expected folio refcount. + * Returns: the expected folio refcount. */ static inline int folio_expected_ref_count(const struct folio *folio) { @@ -4364,6 +4364,45 @@ static inline void mmap_action_simple_ioremap(struct= vm_area_desc *desc, action->type =3D MMAP_SIMPLE_IO_REMAP; } =20 +/** + * mmap_action_map_kernel_pages - helper for mmap_prepare hook to specify = that + * @num kernel pages contained in the @pages array should be mapped to use= rland + * starting at virtual address @start. + * @desc: The VMA descriptor for the VMA requiring kernel pags to be mappe= d. + * @start: The virtual address from which to map them. + * @pages: An array of struct page pointers describing the memory to map. + * @nr_pages: The number of entries in the @pages aray. + */ +static inline void mmap_action_map_kernel_pages(struct vm_area_desc *desc, + unsigned long start, struct page **pages, + unsigned long nr_pages) +{ + struct mmap_action *action =3D &desc->action; + + action->type =3D MMAP_MAP_KERNEL_PAGES; + action->map_kernel.start =3D start; + action->map_kernel.pages =3D pages; + action->map_kernel.nr_pages =3D nr_pages; + action->map_kernel.pgoff =3D desc->pgoff; +} + +/** + * mmap_action_map_kernel_pages_full - helper for mmap_prepare hook to spe= cify that + * kernel pages contained in the @pages array should be mapped to userland + * from @desc->start to @desc->end. + * @desc: The VMA descriptor for the VMA requiring kernel pags to be mappe= d. + * @pages: An array of struct page pointers describing the memory to map. + * + * The caller must ensure that @pages contains sufficient entries to cover= the + * entire range described by @desc. + */ +static inline void mmap_action_map_kernel_pages_full(struct vm_area_desc *= desc, + struct page **pages) +{ + mmap_action_map_kernel_pages(desc, desc->start, pages, + vma_desc_pages(desc)); +} + int mmap_action_prepare(struct vm_area_desc *desc); int mmap_action_complete(struct vm_area_struct *vma, struct mmap_action *action); @@ -4380,10 +4419,59 @@ static inline struct vm_area_struct *find_exact_vma= (struct mm_struct *mm, return vma; } =20 +/** + * range_is_subset - Is the specified inner range a subset of the outer ra= nge? + * @outer_start: The start of the outer range. + * @outer_end: The exclusive end of the outer range. + * @inner_start: The start of the inner range. + * @inner_end: The exclusive end of the inner range. + * + * Returns: %true if [inner_start, inner_end) is a subset of [outer_start, + * outer_end), otherwise %false. + */ +static inline bool range_is_subset(unsigned long outer_start, + unsigned long outer_end, + unsigned long inner_start, + unsigned long inner_end) +{ + return outer_start <=3D inner_start && inner_end <=3D outer_end; +} + +/** + * range_in_vma - is the specified [@start, @end) range a subset of the VM= A? + * @vma: The VMA against which we want to check [@start, @end). + * @start: The start of the range we wish to check. + * @end: The exclusive end of the range we wish to check. + * + * Returns: %true if [@start, @end) is a subset of [@vma->vm_start, + * @vma->vm_end), %false otherwise. + */ static inline bool range_in_vma(const struct vm_area_struct *vma, unsigned long start, unsigned long end) { - return (vma && vma->vm_start <=3D start && end <=3D vma->vm_end); + if (!vma) + return false; + + return range_is_subset(vma->vm_start, vma->vm_end, start, end); +} + +/** + * range_in_vma_desc - is the specified [@start, @end) range a subset of t= he VMA + * described by @desc, a VMA descriptor? + * @desc: The VMA descriptor against which we want to check [@start, @end). + * @start: The start of the range we wish to check. + * @end: The exclusive end of the range we wish to check. + * + * Returns: %true if [@start, @end) is a subset of [@desc->start, @desc->e= nd), + * %false otherwise. + */ +static inline bool range_in_vma_desc(const struct vm_area_desc *desc, + unsigned long start, unsigned long end) +{ + if (!desc) + return false; + + return range_is_subset(desc->start, desc->end, start, end); } =20 #ifdef CONFIG_MMU @@ -4427,6 +4515,9 @@ int remap_pfn_range(struct vm_area_struct *vma, unsig= ned long addr, int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct pag= e *); int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr, struct page **pages, unsigned long *num); +int map_kernel_pages_prepare(struct vm_area_desc *desc); +int map_kernel_pages_complete(struct vm_area_struct *vma, + struct mmap_action *action); int vm_map_pages(struct vm_area_struct *vma, struct page **pages, unsigned long num); int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index d60eefde1db8..f9face579072 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -815,6 +815,7 @@ enum mmap_action_type { MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ + MMAP_MAP_KERNEL_PAGES, /* Map kernel page range from array. */ }; =20 /* @@ -833,6 +834,12 @@ struct mmap_action { phys_addr_t start_phys_addr; unsigned long size; } simple_ioremap; + struct { + unsigned long start; + struct page **pages; + unsigned long nr_pages; + pgoff_t pgoff; + } map_kernel; }; enum mmap_action_type type; =20 diff --git a/mm/memory.c b/mm/memory.c index b3bcc21af20a..53ef8ef3d04a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2484,13 +2484,14 @@ static int insert_pages(struct vm_area_struct *vma,= unsigned long addr, int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr, struct page **pages, unsigned long *num) { - const unsigned long end_addr =3D addr + (*num * PAGE_SIZE) - 1; + const unsigned long nr_pages =3D *num; + const unsigned long end =3D addr + PAGE_SIZE * nr_pages; =20 - if (addr < vma->vm_start || end_addr >=3D vma->vm_end) + if (!range_in_vma(vma, addr, end)) return -EFAULT; if (!(vma->vm_flags & VM_MIXEDMAP)) { - BUG_ON(mmap_read_trylock(vma->vm_mm)); - BUG_ON(vma->vm_flags & VM_PFNMAP); + VM_WARN_ON_ONCE(mmap_read_trylock(vma->vm_mm)); + VM_WARN_ON_ONCE(vma->vm_flags & VM_PFNMAP); vm_flags_set(vma, VM_MIXEDMAP); } /* Defer page refcount checking till we're about to map that page. */ @@ -2498,6 +2499,39 @@ int vm_insert_pages(struct vm_area_struct *vma, unsi= gned long addr, } EXPORT_SYMBOL(vm_insert_pages); =20 +int map_kernel_pages_prepare(struct vm_area_desc *desc) +{ + const struct mmap_action *action =3D &desc->action; + const unsigned long addr =3D action->map_kernel.start; + unsigned long nr_pages, end; + + if (!vma_desc_test(desc, VMA_MIXEDMAP_BIT)) { + VM_WARN_ON_ONCE(mmap_read_trylock(desc->mm)); + VM_WARN_ON_ONCE(vma_desc_test(desc, VMA_PFNMAP_BIT)); + vma_desc_set_flags(desc, VMA_MIXEDMAP_BIT); + } + + nr_pages =3D action->map_kernel.nr_pages; + end =3D addr + PAGE_SIZE * nr_pages; + if (!range_in_vma_desc(desc, addr, end)) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL(map_kernel_pages_prepare); + +int map_kernel_pages_complete(struct vm_area_struct *vma, + struct mmap_action *action) +{ + unsigned long nr_pages; + + nr_pages =3D action->map_kernel.nr_pages; + return insert_pages(vma, action->map_kernel.start, + action->map_kernel.pages, + &nr_pages, vma->vm_page_prot); +} +EXPORT_SYMBOL(map_kernel_pages_complete); + /** * vm_insert_page - insert single page into user vma * @vma: user vma to map to diff --git a/mm/util.c b/mm/util.c index 5ae20876ef2c..f063fd4de1e8 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1448,6 +1448,8 @@ int mmap_action_prepare(struct vm_area_desc *desc) return io_remap_pfn_range_prepare(desc); case MMAP_SIMPLE_IO_REMAP: return simple_ioremap_prepare(desc); + case MMAP_MAP_KERNEL_PAGES: + return map_kernel_pages_prepare(desc); } =20 WARN_ON_ONCE(1); @@ -1475,6 +1477,9 @@ int mmap_action_complete(struct vm_area_struct *vma, case MMAP_REMAP_PFN: err =3D remap_pfn_range_complete(vma, action); break; + case MMAP_MAP_KERNEL_PAGES: + err =3D map_kernel_pages_complete(vma, action); + break; case MMAP_IO_REMAP_PFN: case MMAP_SIMPLE_IO_REMAP: /* Should have been delegated. */ @@ -1495,6 +1500,7 @@ int mmap_action_prepare(struct vm_area_desc *desc) case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: case MMAP_SIMPLE_IO_REMAP: + case MMAP_MAP_KERNEL_PAGES: WARN_ON_ONCE(1); /* nommu cannot handle these. */ break; } @@ -1514,6 +1520,7 @@ int mmap_action_complete(struct vm_area_struct *vma, case MMAP_REMAP_PFN: case MMAP_IO_REMAP_PFN: case MMAP_SIMPLE_IO_REMAP: + case MMAP_MAP_KERNEL_PAGES: WARN_ON_ONCE(1); /* nommu cannot handle this. */ =20 err =3D -EINVAL; diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index f5f7c45f1808..60f0b15638d0 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -454,6 +454,7 @@ enum mmap_action_type { MMAP_REMAP_PFN, /* Remap PFN range. */ MMAP_IO_REMAP_PFN, /* I/O remap PFN range. */ MMAP_SIMPLE_IO_REMAP, /* I/O remap with guardrails. */ + MMAP_MAP_KERNEL_PAGES, /* Map kernel page range from an array. */ }; =20 /* @@ -472,6 +473,12 @@ struct mmap_action { phys_addr_t start_phys_addr; unsigned long size; } simple_ioremap; + struct { + unsigned long start; + struct page **pages; + unsigned long nr_pages; + pgoff_t pgoff; + } map_kernel; }; enum mmap_action_type type; =20 --=20 2.53.0 From nobody Sat Apr 4 01:45:59 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8FC7D3D0921; Fri, 20 Mar 2026 22:41:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046465; cv=none; b=hS4Zcgfj9ABwF1K+n4MHHM3GzBWB7ykkjs1RGB53BY85sd5iWRNn6jgn3DoRd9MMuHaDMDhYji4YSN/K2Y+VqMDTpGrvHrWx4P8CI7dZ8H0soG6YJUI4P/HXo4DYd8SB5ilBxCuPDQeA4s9T/bd3YCNsbeyqf3wlDiAcmp24S5M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774046465; c=relaxed/simple; bh=8qR80FHVrw1W7dNRTWXARimuDYTsH7/Z1DNv6yL8KUI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fmZGr6edWGtqZz0Xl77txGw6bZPoUNJqFF9CKtRZEcfdlnuOeQoCeF+/72oCgU2eX0MC9Nlj44Y3EyonxMChmQ3F31JWn0olGksZUbqTVmbIvBXomLg7PW6/lOW1Q8ehgHyhkhw6UxK1YD8eBYxhYtC7rgjmN7OsiRmhrtQiitM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y5lVmyuB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Y5lVmyuB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7BA36C4CEF7; Fri, 20 Mar 2026 22:41:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774046465; bh=8qR80FHVrw1W7dNRTWXARimuDYTsH7/Z1DNv6yL8KUI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y5lVmyuBl/YHtF0SUASv3ZsIQ1natPUk22znSNUOoj9GyIsqTvNjDfuA4n6b+bsdY 0IktpYP0BWJT+oAlqd91mH+ucfqkC0/or3yrh+9mqekZCcnZ68PC+3+GOlR+kG/Gqk qR3lrrIWipYfuWAhUod8000ikrQiwAYZOzekjarGe48HdLKV5DVaWMA5C5CGo49xdA LZZnpmr2iLBxtmHqo8tPDQrQ9okPRHfMxpwhKc1UaJ49bwA70Zc8q8d7EItWlI2LcM BcStZ6sq6rzSZ540KpAs0bxeFgzoEwLwBn4HNb9lYff6pOhtpLKVcI0Nxiz30+Upqb ALlXbBOZOjIoA== From: "Lorenzo Stoakes (Oracle)" To: Andrew Morton Cc: Jonathan Corbet , Clemens Ladisch , Arnd Bergmann , Greg Kroah-Hartman , "K . Y . Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Bodo Stroesser , "Martin K . Petersen" , David Howells , Marc Dionne , Alexander Viro , Christian Brauner , Jan Kara , David Hildenbrand , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, linux-staging@lists.linux.dev, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, Ryan Roberts Subject: [PATCH v4 21/21] mm: on remap assert that input range within the proposed VMA Date: Fri, 20 Mar 2026 22:39:47 +0000 Message-ID: <0fc1092f4b74f3f673a58e4e3942dc83f336dd85.1774045440.git.ljs@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now we have range_in_vma_desc(), update remap_pfn_range_prepare() to check whether the input range in contained within the specified VMA, so we can fail at prepare time if an invalid range is specified. This covers the I/O remap mmap actions also which ultimately call into this function, and other mmap action types either already span the full VMA or check this already. Reviewed-by: Suren Baghdasaryan Signed-off-by: Lorenzo Stoakes (Oracle) Acked-by: Vlastimil Babka (SUSE) --- mm/memory.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index 53ef8ef3d04a..68cc592ff0ba 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3142,6 +3142,9 @@ int remap_pfn_range_prepare(struct vm_area_desc *desc) const bool is_cow =3D vma_desc_is_cow_mapping(desc); int err; =20 + if (!range_in_vma_desc(desc, start, end)) + return -EFAULT; + err =3D get_remap_pgoff(is_cow, start, end, desc->start, desc->end, pfn, &desc->pgoff); if (err) --=20 2.53.0