* [PATCH v3 09/16] mtdchar: replace deprecated mmap hook with mmap_prepare, clean up
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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 <richard@nod.at>
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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 file *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 = file->private_data;
- struct mtd_info *mtd = mfi->mtd;
- struct map_info *map = 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 == MTD_RAM || mtd->type == MTD_ROM*/) {
-#ifdef pgprot_noncached
- if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
- vma->vm_page_prot = 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
}
@@ -1411,7 +1396,7 @@ static const struct file_operations mtd_fops = {
#endif
.open = mtdchar_open,
.release = mtdchar_close,
- .mmap = mtdchar_mmap,
+ .mmap_prepare = mtdchar_mmap_prepare,
#ifndef CONFIG_MMU
.get_unmapped_area = mtdchar_get_unmapped_area,
.mmap_capabilities = mtdchar_mmap_capabilities,
--
2.53.0
^ permalink raw reply related
* [PATCH v3 08/16] hpet: replace deprecated mmap hook with mmap_prepare
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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 <surenb@google.com>
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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=", hpet_mmap_enable);
-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 = desc->file;
struct hpet_dev *devp;
unsigned long addr;
@@ -368,11 +369,12 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
if (addr & (PAGE_SIZE - 1))
return -ENOSYS;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return vm_iomap_memory(vma, addr, PAGE_SIZE);
+ desc->page_prot = 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 = {
.open = hpet_open,
.release = hpet_release,
.fasync = hpet_fasync,
- .mmap = hpet_mmap,
+ .mmap_prepare = hpet_mmap_prepare,
};
static int hpet_is_known(struct hpet_data *hdp)
--
2.53.0
^ permalink raw reply related
* [PATCH v3 07/16] misc: open-dice: replace deprecated mmap hook with mmap_prepare
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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 <surenb@google.com>
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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 = desc->file;
struct open_dice_drvdata *drvdata = to_open_dice_drvdata(filp);
- 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);
}
/* Create write-combine mapping so all clients observe a wipe. */
- vma->vm_page_prot = 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 = 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;
}
static const struct file_operations open_dice_fops = {
.owner = THIS_MODULE,
.read = open_dice_read,
.write = open_dice_write,
- .mmap = open_dice_mmap,
+ .mmap_prepare = open_dice_mmap_prepare,
};
static int __init open_dice_probe(struct platform_device *pdev)
--
2.53.0
^ permalink raw reply related
* [PATCH v3 06/16] mm: add mmap_action_simple_ioremap()
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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 <surenb@google.com>
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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/filesystems/mmap_prepare.rst
index 20db474915da..be76ae475b9c 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.
+* 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 directly,
rather you ought to use one of these helpers.
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 68dee1101313..ef2e4dccfe8e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4337,11 +4337,33 @@ static inline void mmap_action_ioremap(struct vm_area_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));
}
+/**
+ * mmap_action_simple_ioremap - helper for mmap_prepare hook to specify that 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 = &desc->action;
+
+ action->simple_ioremap.start_phys_addr = start_phys_addr;
+ action->simple_ioremap.size = size;
+ action->type = 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 4a229cc0a06b..50685cf29792 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. */
};
/*
@@ -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;
diff --git a/mm/internal.h b/mm/internal.h
index e0f554178143..2aa04d87ac10 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1804,6 +1804,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);
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);
}
+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 += start_phys & ~PAGE_MASK;
+ pfn = start_phys >> PAGE_SHIFT;
+ pages = (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 += vm_pgoff;
+ pages -= vm_pgoff;
+
+ /* Can we fit all of the mapping? */
+ if ((vm_len >> PAGE_SHIFT) > pages)
+ return -EINVAL;
+
+ *pfnp = pfn;
+ return 0;
+}
+
+int simple_ioremap_prepare(struct vm_area_desc *desc)
+{
+ struct mmap_action *action = &desc->action;
+ const phys_addr_t start = action->simple_ioremap.start_phys_addr;
+ const unsigned long size = action->simple_ioremap.size;
+ unsigned long pfn;
+ int err;
+
+ err = __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, unsigned 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 += start & ~PAGE_MASK;
- pfn = start >> PAGE_SHIFT;
- pages = (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 += vma->vm_pgoff;
- pages -= vma->vm_pgoff;
+ const unsigned long vm_start = vma->vm_start;
+ const unsigned long vm_end = vma->vm_end;
+ const unsigned long vm_len = vm_end - vm_start;
+ unsigned long pfn;
+ int err;
- /* Can we fit all of the mapping? */
- vm_len = vma->vm_end - vma->vm_start;
- if (vm_len >> PAGE_SHIFT > pages)
- return -EINVAL;
+ err = __simple_ioremap_prep(vm_len, vma->vm_pgoff, start, len, &pfn);
+ if (err)
+ return err;
/* Ok, let it rip */
return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
diff --git a/mm/util.c b/mm/util.c
index fc1bd8a8f3ea..879ba62b5f0c 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1392,6 +1392,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);
}
WARN_ON_ONCE(1);
@@ -1423,6 +1425,7 @@ int mmap_action_complete(struct vm_area_struct *vma,
err = 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 = -EINVAL;
@@ -1441,6 +1444,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;
}
@@ -1460,6 +1464,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. */
err = -EINVAL;
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index aa34966cbc62..1b86c34e1158 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. */
};
/*
@@ -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;
--
2.53.0
^ permalink raw reply related
* [PATCH v3 05/16] fs: afs: correctly drop reference count on mapping failure
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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.
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).
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) <ljs@kernel.org>
---
fs/afs/file.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/fs/afs/file.c b/fs/afs/file.c
index f609366fd2ac..85696ac984cc 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -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_pgoff, pgoff_t end_pgoff);
+static int afs_mapped(unsigned long start, unsigned long end, pgoff_t pgoff,
+ const struct file *file, void **vm_private_data);
const struct file_operations afs_file_operations = {
.open = afs_open,
@@ -61,6 +63,7 @@ const struct address_space_operations afs_file_aops = {
};
static const struct vm_operations_struct afs_vm_ops = {
+ .mapped = afs_mapped,
.open = afs_vm_open,
.close = afs_vm_close,
.fault = filemap_fault,
@@ -494,32 +497,45 @@ static void afs_drop_open_mmap(struct afs_vnode *vnode)
*/
static int afs_file_mmap_prepare(struct vm_area_desc *desc)
{
- struct afs_vnode *vnode = AFS_FS_I(file_inode(desc->file));
int ret;
- afs_add_open_mmap(vnode);
-
ret = generic_file_mmap_prepare(desc);
- if (ret == 0)
- desc->vm_ops = &afs_vm_ops;
- else
- afs_drop_open_mmap(vnode);
+ if (ret)
+ return ret;
+
+ desc->vm_ops = &afs_vm_ops;
return ret;
}
+static int afs_mapped(unsigned long start, unsigned long end, pgoff_t pgoff,
+ const struct file *file, void **vm_private_data)
+{
+ struct afs_vnode *vnode = 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 = vma->vm_file;
+ struct afs_vnode *vnode = 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 = vma->vm_file;
+ struct afs_vnode *vnode = 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_pgoff, pgoff_t end_pgoff)
{
- struct afs_vnode *vnode = AFS_FS_I(file_inode(vmf->vma->vm_file));
+ struct file *file = vmf->vma->vm_file;
+ struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
if (afs_check_validity(vnode))
return filemap_map_pages(vmf, start_pgoff, end_pgoff);
--
2.53.0
^ permalink raw reply related
* [PATCH v3 04/16] mm: add vm_ops->mapped hook
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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.
We can now also remove call_action_complete() and invoke
mmap_action_complete() directly, as we separate out the rmap lock logic.
The rmap lock logic, which was added in order to keep hugetlb working (!)
to allow for the rmap lock to be held longer, needs to be propagated to the
error paths on mmap complete and mapped hook error paths.
This is because do_munmap() might otherwise deadlock with the rmap being
held, so instead we unlock at the point of unmap.
This is fine as any reliance on the rmap being held is irrelevant on error.
While we're here, refactor mmap_action_finish() to avoid a big if (err)
branch.
We also abstract unmapping of a VMA on mmap action completion into its own
helper function, unmap_vma_locked().
Update the mmap_prepare documentation to describe the mapped hook and make
it clear what its intended use is.
Additionally, update VMA userland test headers to reflect the change.
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
Documentation/filesystems/mmap_prepare.rst | 15 +++
include/linux/fs.h | 9 +-
include/linux/mm.h | 20 +++-
mm/internal.h | 8 ++
mm/util.c | 129 ++++++++++++++-------
mm/vma.c | 35 +++---
tools/testing/vma/include/dup.h | 27 ++++-
tools/testing/vma/include/stubs.h | 3 +-
8 files changed, 186 insertions(+), 60 deletions(-)
diff --git a/Documentation/filesystems/mmap_prepare.rst b/Documentation/filesystems/mmap_prepare.rst
index 65a1f094e469..20db474915da 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 updated 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.
+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->mapped``
+hook, which itself should be set by the >mmap_prepare hook.
+
+This callback is only invoked if a new mapping has been established and was 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 mapping 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
==========
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)
}
int compat_vma_mmap(struct file *file, struct vm_area_struct *vma);
+int __vma_check_mmap_hook(struct vm_area_struct *vma);
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);
- return file->f_op->mmap(file, vma);
+ err = file->f_op->mmap(file, vma);
+ if (err)
+ return err;
+
+ return __vma_check_mmap_hook(vma);
}
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..68dee1101313 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);
@@ -4327,7 +4344,8 @@ static inline void mmap_action_ioremap_full(struct vm_area_desc *desc,
int mmap_action_prepare(struct vm_area_desc *desc);
int mmap_action_complete(struct vm_area_struct *vma,
- struct mmap_action *action);
+ struct mmap_action *action,
+ bool rmap_lock_held);
/* 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 0256ca44115a..e0f554178143 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -202,6 +202,14 @@ static inline void vma_close(struct vm_area_struct *vma)
/* unmap_vmas is in mm/memory.c */
void unmap_vmas(struct mmu_gather *tlb, struct unmap_desc *unmap);
+static inline void unmap_vma_locked(struct vm_area_struct *vma)
+{
+ const size_t len = vma_pages(vma) << PAGE_SHIFT;
+
+ mmap_assert_write_locked(vma->vm_mm);
+ do_munmap(vma->vm_mm, vma->vm_start, len, NULL);
+}
+
#ifdef CONFIG_MMU
static inline void get_anon_vma(struct anon_vma *anon_vma)
diff --git a/mm/util.c b/mm/util.c
index 73c97a748d8e..fc1bd8a8f3ea 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1163,6 +1163,54 @@ void flush_dcache_folio(struct folio *folio)
EXPORT_SYMBOL(flush_dcache_folio);
#endif
+static int __compat_vma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct vm_area_desc desc = {
+ .mm = vma->vm_mm,
+ .file = file,
+ .start = vma->vm_start,
+ .end = vma->vm_end,
+
+ .pgoff = vma->vm_pgoff,
+ .vm_file = vma->vm_file,
+ .vma_flags = vma->flags,
+ .page_prot = vma->vm_page_prot,
+
+ .action.type = MMAP_NOTHING, /* Default */
+ };
+ int err;
+
+ err = vfs_mmap_prepare(file, &desc);
+ if (err)
+ return err;
+
+ err = mmap_action_prepare(&desc);
+ if (err)
+ return err;
+
+ set_vma_from_desc(vma, &desc);
+ return mmap_action_complete(vma, &desc.action, /*rmap_lock_held=*/false);
+}
+
+static int __compat_vma_mapped(struct file *file, struct vm_area_struct *vma)
+{
+ const struct vm_operations_struct *vm_ops = vma->vm_ops;
+ void *vm_private_data = vma->vm_private_data;
+ int err;
+
+ if (!vm_ops || !vm_ops->mapped)
+ return 0;
+
+ err = vm_ops->mapped(vma->vm_start, vma->vm_end, vma->vm_pgoff, file,
+ &vm_private_data);
+ if (err)
+ unmap_vma_locked(vma);
+ else if (vm_private_data != vma->vm_private_data)
+ vma->vm_private_data = vm_private_data;
+
+ return err;
+}
+
/**
* compat_vma_mmap() - Apply the file's .mmap_prepare() hook to an
* existing VMA and execute any requested actions.
@@ -1191,34 +1239,26 @@ EXPORT_SYMBOL(flush_dcache_folio);
*/
int compat_vma_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct vm_area_desc desc = {
- .mm = vma->vm_mm,
- .file = file,
- .start = vma->vm_start,
- .end = vma->vm_end,
-
- .pgoff = vma->vm_pgoff,
- .vm_file = vma->vm_file,
- .vma_flags = vma->flags,
- .page_prot = vma->vm_page_prot,
-
- .action.type = MMAP_NOTHING, /* Default */
- };
int err;
- err = vfs_mmap_prepare(file, &desc);
+ err = __compat_vma_mmap(file, vma);
if (err)
return err;
- err = mmap_action_prepare(&desc);
- if (err)
- return err;
-
- set_vma_from_desc(vma, &desc);
- return mmap_action_complete(vma, &desc.action);
+ return __compat_vma_mapped(file, vma);
}
EXPORT_SYMBOL(compat_vma_mmap);
+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 *folio,
const struct page *page)
{
@@ -1308,32 +1348,31 @@ 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)
+ struct mmap_action *action, int err,
+ bool rmap_lock_held)
{
+ if (rmap_lock_held)
+ i_mmap_unlock_write(vma->vm_file->f_mapping);
+
+ if (!err) {
+ if (action->success_hook)
+ return action->success_hook(vma);
+ 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) {
- const size_t len = 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 = action->error_hook(err);
-
- /* The caller should not clear the error. */
- VM_WARN_ON_ONCE(!err);
- }
- return err;
+ unmap_vma_locked(vma);
+ if (action->error_hook) {
+ /* We may want to filter the error. */
+ err = 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
@@ -1364,13 +1403,15 @@ EXPORT_SYMBOL(mmap_action_prepare);
* mmap_action_complete - Execute VMA descriptor action.
* @vma: The VMA to perform the action upon.
* @action: The action to perform.
+ * @rmap_lock_held: Is the file rmap lock held?
*
* Similar to mmap_action_prepare().
*
* Return: 0 on success, or error, at which point the VMA will be unmapped.
*/
int mmap_action_complete(struct vm_area_struct *vma,
- struct mmap_action *action)
+ struct mmap_action *action,
+ bool rmap_lock_held)
{
int err = 0;
@@ -1388,7 +1429,8 @@ int mmap_action_complete(struct vm_area_struct *vma,
break;
}
- return mmap_action_finish(vma, action, err);
+ return mmap_action_finish(vma, action, err,
+ rmap_lock_held);
}
EXPORT_SYMBOL(mmap_action_complete);
#else
@@ -1408,7 +1450,8 @@ int mmap_action_prepare(struct vm_area_desc *desc)
EXPORT_SYMBOL(mmap_action_prepare);
int mmap_action_complete(struct vm_area_struct *vma,
- struct mmap_action *action)
+ struct mmap_action *action,
+ bool rmap_lock_held)
{
int err = 0;
@@ -1423,7 +1466,7 @@ int mmap_action_complete(struct vm_area_struct *vma,
break;
}
- return mmap_action_finish(vma, action, err);
+ return mmap_action_finish(vma, action, err, rmap_lock_held);
}
EXPORT_SYMBOL(mmap_action_complete);
#endif
diff --git a/mm/vma.c b/mm/vma.c
index 2a86c7575000..a27d1278ea6d 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2731,21 +2731,28 @@ static bool can_set_ksm_flags_early(struct mmap_state *map)
return false;
}
-static int call_action_complete(struct mmap_state *map,
- struct mmap_action *action,
- struct vm_area_struct *vma)
+static int call_mapped_hook(struct mmap_state *map,
+ struct vm_area_struct *vma)
{
- int ret;
-
- ret = mmap_action_complete(vma, action);
+ const struct vm_operations_struct *vm_ops = vma->vm_ops;
+ void *vm_private_data = vma->vm_private_data;
+ int err;
- /* If we held the file rmap we need to release it. */
- if (map->hold_file_rmap_lock) {
- struct file *file = vma->vm_file;
+ if (!vm_ops || !vm_ops->mapped)
+ return 0;
+ err = vm_ops->mapped(vma->vm_start, vma->vm_end, vma->vm_pgoff,
+ vma->vm_file, &vm_private_data);
+ if (err) {
+ if (map->hold_file_rmap_lock)
+ i_mmap_unlock_write(vma->vm_file->f_mapping);
- i_mmap_unlock_write(file->f_mapping);
+ unmap_vma_locked(vma);
+ return err;
}
- return ret;
+ /* Update private data if changed. */
+ if (vm_private_data != vma->vm_private_data)
+ vma->vm_private_data = vm_private_data;
+ return 0;
}
static unsigned long __mmap_region(struct file *file, unsigned long addr,
@@ -2799,8 +2806,10 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
__mmap_complete(&map, vma);
if (have_mmap_prepare && allocated_new) {
- error = call_action_complete(&map, &desc.action, vma);
-
+ error = mmap_action_complete(vma, &desc.action,
+ map.hold_file_rmap_lock);
+ if (!error)
+ error = call_mapped_hook(&map, vma);
if (error)
return error;
}
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 8ae525ed1738..aa34966cbc62 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);
@@ -1281,7 +1298,7 @@ static inline int __compat_vma_mmap(const struct file_operations *f_op,
return err;
set_vma_from_desc(vma, &desc);
- return mmap_action_complete(vma, &desc.action);
+ return mmap_action_complete(vma, &desc.action, /*rmap_lock_held=*/false);
}
static inline int compat_vma_mmap(struct file *file,
@@ -1500,3 +1517,11 @@ static inline pgprot_t vma_get_page_prot(vma_flags_t vma_flags)
return vm_get_page_prot(vm_flags);
}
+
+static inline void unmap_vma_locked(struct vm_area_struct *vma)
+{
+ const size_t len = vma_pages(vma) << PAGE_SHIFT;
+
+ mmap_assert_write_locked(vma->vm_mm);
+ do_munmap(vma->vm_mm, vma->vm_start, len, NULL);
+}
diff --git a/tools/testing/vma/include/stubs.h b/tools/testing/vma/include/stubs.h
index a30b8bc84955..d1c3d4ddb5e9 100644
--- a/tools/testing/vma/include/stubs.h
+++ b/tools/testing/vma/include/stubs.h
@@ -87,7 +87,8 @@ static inline int mmap_action_prepare(struct vm_area_desc *desc)
}
static inline int mmap_action_complete(struct vm_area_struct *vma,
- struct mmap_action *action)
+ struct mmap_action *action,
+ bool rmap_lock_held)
{
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v3 03/16] mm: document vm_operations_struct->open the same as close()
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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'.
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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);
/* 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/dup.h
index 9eada1e0949c..8ae525ed1738 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;
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);
/* notification that a previously read-only page is about to become
* writable, if an error is returned it will cause a SIGBUS */
--
2.53.0
^ permalink raw reply related
* [PATCH v3 02/16] mm: add documentation for the mmap_prepare file operation callback
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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.
Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
---
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/filesystems/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/filesystems/mmap_prepare.rst
new file mode 100644
index 000000000000..65a1f094e469
--- /dev/null
+++ b/Documentation/filesystems/mmap_prepare.rst
@@ -0,0 +1,142 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================
+mmap_prepare callback HOWTO
+===========================
+
+Introduction
+============
+
+The ``struct file->f_op->mmap()`` callback has been deprecated as it is both a
+stability and security risk, and doesn't always permit the merging of adjacent
+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 taken
+place.
+
+If an error arises upon mapping, it might arise after this callback has been
+invoked, therefore it should be treated as effectively stateless.
+
+That is - no resources should be allocated nor state updated 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.
+
+How To Use
+==========
+
+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 = {
+ ...
+ .mmap_prepare = 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 callers. */
+ 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 = desc->file;
+ struct inode *inode = file->f_mapping->host;
+
+ ...
+
+ file_accessed(file);
+ if (IS_DAX(file_inode(file))) {
+ desc->vm_ops = &ext4_dax_vm_ops;
+ vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT);
+ } else {
+ desc->vm_ops = &ext4_file_vm_ops;
+ }
+ return 0;
+ }
+
+Importantly, you no longer have to dance around with reference counts or locks
+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 before
+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_WRITE``,
+etc. - i.e. using a ``-VM_xxx``- macro has changed too.
+
+When implementing mmap_prepare(), reference flags by their bit number, defined
+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_flags(desc, ...)`` - Specify a comma-separated list of flags
+ you wish to test for (whether _any_ are set), e.g. - ``vma_desc_test_flags(
+ desc, VMA_WRITE_BIT, VMA_MAYWRITE_BIT)`` - returns ``true`` if either are set,
+ otherwise ``false``.
+* ``vma_desc_set_flags(desc, ...)`` - Update the VMA descriptor flags to set
+ 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
+=======
+
+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 specific
+ 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 directly,
+rather you ought to use one of these helpers.
--
2.53.0
^ permalink raw reply related
* [PATCH v3 01/16] mm: various small mmap_prepare cleanups
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <cover.1773944114.git.ljs@kernel.org>
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) <ljs@kernel.org>
---
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;
}
-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);
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 vm_area_desc *desc,
mmap_action_ioremap(desc, desc->start, start_pfn, vma_desc_size(desc));
}
-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);
/* 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, unsigned 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);
-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 addr,
- 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);
-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 = &desc->action;
+ const unsigned long orig_pfn = action->remap.start_pfn;
+ const pgprot_t orig_pgprot = action->remap.pgprot;
+ const unsigned long size = action->remap.size;
const unsigned long pfn = io_remap_pfn_range_pfn(orig_pfn, size);
+ int err;
- return remap_pfn_range_prepare(desc, pfn);
-}
+ action->remap.start_pfn = pfn;
+ action->remap.pgprot = pgprot_decrypted(orig_pgprot);
+ err = remap_pfn_range_prepare(desc);
+ if (err)
+ return err;
-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 = io_remap_pfn_range_pfn(orig_pfn, size);
- const pgprot_t prot = pgprot_decrypted(orig_prot);
-
- return remap_pfn_range_complete(vma, addr, pfn, size, prot);
+ /* Remap does the actual work. */
+ action->type = MMAP_REMAP_PFN;
+ return 0;
}
#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
-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=VMA start, end=VMA 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 = &desc->action;
+ const unsigned long start = action->remap.start;
+ const unsigned long end = start + action->remap.size;
+ const unsigned long pfn = action->remap.start_pfn;
+ const bool is_cow = vma_desc_is_cow_mapping(desc);
+ int err;
+
+ err = 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;
}
-static int remap_pfn_range_prepare_vma(struct vm_area_struct *vma, unsigned 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 = addr + PAGE_ALIGN(size);
+ const unsigned long end = addr + PAGE_ALIGN(size);
+ const bool is_cow = is_cow_mapping(vma->vm_flags);
int err;
- err = get_remap_pgoff(is_cow_mapping(vma->vm_flags), addr, end,
- vma->vm_start, vma->vm_end, pfn, &vma->vm_pgoff);
+ err = get_remap_pgoff(is_cow, addr, end, vma->vm_start, vma->vm_end,
+ pfn, &vma->vm_pgoff);
if (err)
return err;
@@ -3151,10 +3159,15 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
}
EXPORT_SYMBOL(remap_pfn_range);
-int remap_pfn_range_complete(struct vm_area_struct *vma, unsigned long addr,
- 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 = action->remap.start;
+ const unsigned long pfn = action->remap.start_pfn;
+ const unsigned long size = action->remap.size;
+ const pgprot_t prot = action->remap.pgprot;
+
+ return do_remap_pfn_range(vma, start, pfn, size, prot);
}
/**
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
-/**
- * __compat_vma_mmap() - See description for compat_vma_mmap()
- * for details. This is the same operation, only with a specific file operations
- * 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 = {
- .mm = vma->vm_mm,
- .file = file,
- .start = vma->vm_start,
- .end = vma->vm_end,
-
- .pgoff = vma->vm_pgoff,
- .vm_file = vma->vm_file,
- .vma_flags = vma->flags,
- .page_prot = vma->vm_page_prot,
-
- .action.type = MMAP_NOTHING, /* Default */
- };
- int err;
-
- err = 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 = {
+ .mm = vma->vm_mm,
+ .file = file,
+ .start = vma->vm_start,
+ .end = vma->vm_end,
+
+ .pgoff = vma->vm_pgoff,
+ .vm_file = vma->vm_file,
+ .vma_flags = vma->flags,
+ .page_prot = vma->vm_page_prot,
+
+ .action.type = MMAP_NOTHING, /* Default */
+ };
+ int err;
+
+ err = vfs_mmap_prepare(file, &desc);
+ if (err)
+ return err;
+
+ err = 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);
@@ -1320,8 +1307,8 @@ void snapshot_page(struct page_snapshot *ps, const struct page *page)
}
}
-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 *action,
/**
* 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);
/**
* 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 = 0;
@@ -1391,25 +1379,22 @@ int mmap_action_complete(struct mmap_action *action,
case MMAP_NOTHING:
break;
case MMAP_REMAP_PFN:
- err = remap_pfn_range_complete(vma, action->remap.start,
- action->remap.start_pfn, action->remap.size,
- action->remap.pgprot);
+ err = remap_pfn_range_complete(vma, action);
break;
case MMAP_IO_REMAP_PFN:
- err = 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 = -EINVAL;
break;
}
- 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);
-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 = 0;
@@ -1436,7 +1423,7 @@ int mmap_action_complete(struct mmap_action *action,
break;
}
- 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 c1f183235756..2a86c7575000 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2640,15 +2640,18 @@ static void __mmap_complete(struct mmap_state *map, struct vm_area_struct *vma)
vma_set_page_prot(vma);
}
-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 = &desc->action;
+ int err;
- mmap_action_prepare(action, desc);
+ err = mmap_action_prepare(desc);
+ if (err)
+ return err;
- if (action->hide_from_rmap_until_complete)
+ if (desc->action.hide_from_rmap_until_complete)
map->hold_file_rmap_lock = true;
+ return 0;
}
/*
@@ -2672,7 +2675,9 @@ static int call_mmap_prepare(struct mmap_state *map,
if (err)
return err;
- call_action_prepare(map, desc);
+ err = call_action_prepare(map, desc);
+ if (err)
+ return err;
/* Update fields permitted to be changed. */
map->pgoff = desc->pgoff;
@@ -2727,13 +2732,12 @@ static bool can_set_ksm_flags_early(struct mmap_state *map)
}
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 = &desc->action;
int ret;
- ret = mmap_action_complete(action, vma);
+ ret = mmap_action_complete(vma, action);
/* If we held the file rmap we need to release it. */
if (map->hold_file_rmap_lock) {
@@ -2795,7 +2799,7 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
__mmap_complete(&map, vma);
if (have_mmap_prepare && allocated_new) {
- error = call_action_complete(&map, &desc, vma);
+ error = call_action_complete(&map, &desc.action, vma);
if (error)
return error;
diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
index 999357e18eb0..9eada1e0949c 100644
--- a/tools/testing/vma/include/dup.h
+++ b/tools/testing/vma/include/dup.h
@@ -1271,9 +1271,12 @@ static inline int __compat_vma_mmap(const struct file_operations *f_op,
if (err)
return err;
- mmap_action_prepare(&desc.action, &desc);
+ err = 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);
}
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_struct *vma)
{
}
-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;
}
-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;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v3 00/16] mm: expand mmap_prepare functionality and usage
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 18:23 UTC (permalink / raw)
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, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
This series expands the mmap_prepare functionality, which is intended to
replace the deprecated f_op->mmap hook which has been the source of bugs
and security issues for some time.
This series starts with some cleanup of existing mmap_prepare logic, then
adds documentation for the mmap_prepare call to make it easier for
filesystem and driver writers to understand how it works.
It then importantly adds a vm_ops->mapped hook, a key feature that was
missing from mmap_prepare previously - this is invoked when a driver which
specifies mmap_prepare has successfully been mapped but not merged with
another VMA.
mmap_prepare is invoked prior to a merge being attempted, so you cannot
manipulate state such as reference counts as if it were a new mapping.
The vm_ops->mapped hook allows a driver to perform tasks required at this
stage, and provides symmetry against subsequent vm_ops->open,close calls.
The series uses this to correct the afs implementation which wrongly
manipulated reference count at mmap_prepare time.
It then adds an mmap_prepare equivalent of vm_iomap_memory() -
mmap_action_simple_ioremap(), then uses this to update a number of drivers.
It then splits out the mmap_prepare compatibility layer (which allows for
invocation of mmap_prepare hooks in an mmap() hook) in such a way as to
allow for more incremental implementation of mmap_prepare hooks.
It then uses this to extend mmap_prepare usage in drivers.
Finally it adds an mmap_prepare equivalent of vm_map_pages(), which lays
the foundation for future work which will extend mmap_prepare to DMA
coherent mappings.
v3:
* Propagated tags (thanks Suren, Richard!)
* Updated 12/16 to correctly clear the vm_area_desc data structure in
set_desc_from_vma() as per Joshua Hahn (thanks! :)
* Fixed type in 12/16 as per Suren (cheers!)
* Fixed up 6/16 to use mmap_action_ioremap_full() in simple_ioremap_prepare() as
suggested by Suren.
* Also fixed up 6/16 to call io_remap_pfn_range_prepare() direct rather than
mmap_action_prepare() as per Suren.
* Also fixed up 6/16 to pass vm_len rather than vm_[start, end] to
__simple_ioremap_prep() as per Suren (thanks for all the above! :)
* Fixed issue in rmap lock being held - we were referencing a vma->vm_file after
the VMA was unmapped, so UAF. Avoid that. Also do_munmap() relies on rmap lock
NOT being held or may deadlock, so extend functionality to ensure we drop it
when it is held on error paths.
* Updated 'area' -> 'vma' variable in 3/16 in VMA test dup.h.
* Fixed up reference to __compat_vma_mmap() in 12/16 commit message.
* Updated 1/16 to no longer duplicatively apply io_remap_pfn_range_pfn().
* Updated 1/16 to delegate I/O remap complete to remap complete logic.
* Fixed various typos in 12/16.
* Fixed stale comment typos in 13/16.
* Fixed commit msg and comment typos in 14/16.
* Removed accidental sneak peak to future functionality in 15/16 commit message
:).
* Fixed up field names to be identical in VMA tests + mm_types.h in 6/16,
15/16.
v2:
* Rebased on
https://lore.kernel.org/all/cover.1773665966.git.ljs@kernel.org/ to make
Andrew's life easier :)
* Folded all interim fixes into series (thanks Randy for many doc fixes!))
* As per Suren, removed a comment about allocations too small to fail.
* As per Randy, fixed up typo in documentation for vm_area_desc.
* Fixed mmap_action_prepare() not returning if invalid action->type
specified, as updated from Andrew's interim fix (thanks!) and also
reported by kernel test bot.
* Updated mmap_action_prepare() and specific prepare functions to only
pass vm_area_desc parameter as per Suren.
* Fixed up whitespace as per Suren.
* Updated vm_op->open comment in vm_operations_struct to reference forking
as per Suren.
* Added a commit to check that input range is within VMA on remap as per
Suren (this also covers I/O remap and all other cases already asserted).
* Updated AFS to not incorrectly reference count on mmap prepare as per
Usama.
* Also updated various static AFS functions to be consistent with each
other.
* Updated AFS commit message to reflect mmap_prepare being before any VMA
merging as per Suren.
* Updated __compat_vma_mapped() to check for NULL vm_ops as per Usama.
* Updated __compat_vma_mapped() to not reference an unmapped VMA's fields
as per Usama.
* Updated __vma_check_mmap_hook() to check for NULL vm_ops as per Usama.
* Dropped comment about preferring mmap_prepare as seems overly confusing,
as per Suren.
* Updated the mmap lock assert in unmap_vma_locked() to a write lock assert
as per Suren.
* Copied vm_ops->open comment over to VMA tests in appropriate patch as per
Suren.
* Updated mmap_prepare documentation to reflect the fact that no resources
should be allocated upon mmap_prepare.
* Updated mmap_prepare documentation to reference the vm_ops->mapped
callback.
* Fixed stray markdown '## How to use' in documentation.
* Fixed bug reported by kernel test bot re: overlooked
vma_desc_test_flags() -> vma_desc_test() in MTD driver for nommu.
https://lore.kernel.org/linux-mm/cover.1773695307.git.ljs@kernel.org/
v1:
https://lore.kernel.org/linux-mm/cover.1773346620.git.ljs@kernel.org/
Lorenzo Stoakes (Oracle) (16):
mm: various small mmap_prepare cleanups
mm: add documentation for the mmap_prepare file operation callback
mm: document vm_operations_struct->open the same as close()
mm: add vm_ops->mapped hook
fs: afs: correctly drop reference count on mapping failure
mm: add mmap_action_simple_ioremap()
misc: open-dice: replace deprecated mmap hook with mmap_prepare
hpet: replace deprecated mmap hook with mmap_prepare
mtdchar: replace deprecated mmap hook with mmap_prepare, clean up
stm: replace deprecated mmap hook with mmap_prepare
staging: vme_user: replace deprecated mmap hook with mmap_prepare
mm: allow handling of stacked mmap_prepare hooks in more drivers
drivers: hv: vmbus: replace deprecated mmap hook with mmap_prepare
uio: replace deprecated mmap hook with mmap_prepare in uio_info
mm: add mmap_action_map_kernel_pages[_full]()
mm: on remap assert that input range within the proposed VMA
Documentation/driver-api/vme.rst | 2 +-
Documentation/filesystems/index.rst | 1 +
Documentation/filesystems/mmap_prepare.rst | 168 ++++++++++++++
drivers/char/hpet.c | 12 +-
drivers/hv/hyperv_vmbus.h | 4 +-
drivers/hv/vmbus_drv.c | 31 ++-
drivers/hwtracing/stm/core.c | 31 ++-
drivers/misc/open-dice.c | 19 +-
drivers/mtd/mtdchar.c | 21 +-
drivers/staging/vme_user/vme.c | 20 +-
drivers/staging/vme_user/vme.h | 2 +-
drivers/staging/vme_user/vme_user.c | 51 +++--
drivers/target/target_core_user.c | 26 ++-
drivers/uio/uio.c | 10 +-
drivers/uio/uio_hv_generic.c | 11 +-
fs/afs/file.c | 36 ++-
include/linux/fs.h | 14 +-
include/linux/hyperv.h | 4 +-
include/linux/mm.h | 159 ++++++++++++-
include/linux/mm_types.h | 17 +-
include/linux/uio_driver.h | 4 +-
mm/internal.h | 41 ++--
mm/memory.c | 175 ++++++++++----
mm/util.c | 251 ++++++++++++++-------
mm/vma.c | 53 +++--
mm/vma.h | 2 +-
tools/testing/vma/include/dup.h | 152 ++++++++++---
tools/testing/vma/include/stubs.h | 9 +-
28 files changed, 990 insertions(+), 336 deletions(-)
create mode 100644 Documentation/filesystems/mmap_prepare.rst
--
2.53.0
^ permalink raw reply
* Re: [PATCH v7 07/10] x86/vmscape: Use static_call() for predictor flush
From: Pawan Gupta @ 2026-03-19 18:05 UTC (permalink / raw)
To: bot+bpf-ci
Cc: x86, nik.borisov, hpa, jpoimboe, david.kaplan, seanjc, bp,
dave.hansen, peterz, ast, daniel, andrii, kpsingh, jolsa, davem,
david.laight.linux, luto, tglx, mingo, dsahern, martin.lau,
eddyz87, song, yonghong.song, john.fastabend, sdf, haoluo,
pbonzini, corbet, linux-kernel, kvm, asit.k.mallick, tao1.zhang,
bpf, netdev, linux-doc, martin.lau, clm, ihor.solodrai
In-Reply-To: <dfba37ee6cd5de8954bbc57d18af3e4865e35cdda8535d890ae6380e4a1cc0af@mail.kernel.org>
On Thu, Mar 19, 2026 at 04:56:52PM +0000, bot+bpf-ci@kernel.org wrote:
> > diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> > index 68e2df3e3bf58..b75eda114503a 100644
> > --- a/arch/x86/kernel/cpu/bugs.c
> > +++ b/arch/x86/kernel/cpu/bugs.c
> > @@ -144,6 +144,17 @@ EXPORT_SYMBOL_GPL(cpu_buf_idle_clear);
> > */
> > DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
> >
> > +/*
> > + * Controls CPU Fill buffer clear before VMenter. This is a subset of
> > + * X86_FEATURE_CLEAR_CPU_BUF, and should only be enabled when KVM-only
> > + * mitigation is required.
> > + */
> > +DEFINE_STATIC_KEY_FALSE(cpu_buf_vm_clear);
> > +EXPORT_SYMBOL_GPL(cpu_buf_vm_clear);
>
> cpu_buf_vm_clear is defined and exported here but appears to have no
> users. There is no declaration in any header, and nothing in this
> patch series references it.
>
> The comment describes CPU fill buffer clearing before VMenter, which
> seems unrelated to the predictor flush static_call conversion that
> this patch is doing. Was this included by mistake, or is it intended
> for a follow-up series?
Agh, that is introduced by a wrong conflict resolution during rebase,
removed now.
> > +
> > +DEFINE_STATIC_CALL_NULL(vmscape_predictor_flush, write_ibpb);
> > +EXPORT_STATIC_CALL_GPL(vmscape_predictor_flush);
^ permalink raw reply
* Re: [PATCH v7 10/10] x86/vmscape: Add cmdline vmscape=on to override attack vector controls
From: Pawan Gupta @ 2026-03-19 17:57 UTC (permalink / raw)
To: bot+bpf-ci
Cc: x86, nik.borisov, hpa, jpoimboe, david.kaplan, seanjc, bp,
dave.hansen, peterz, ast, daniel, andrii, kpsingh, jolsa, davem,
david.laight.linux, luto, tglx, mingo, dsahern, martin.lau,
eddyz87, song, yonghong.song, john.fastabend, sdf, haoluo,
pbonzini, corbet, linux-kernel, kvm, asit.k.mallick, tao1.zhang,
bpf, netdev, linux-doc, martin.lau, clm, ihor.solodrai
In-Reply-To: <a0134d85926936821c00147b9602b4f977519556e163ebd59dee2307c7618fb1@mail.kernel.org>
On Thu, Mar 19, 2026 at 04:40:21PM +0000, bot+bpf-ci@kernel.org wrote:
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -8375,9 +8375,11 @@
> >
> > off - disable the mitigation
> > ibpb - use Indirect Branch Prediction Barrier
> > - (IBPB) mitigation (default)
> > + (IBPB) mitigation
> > force - force vulnerability detection even on
> > unaffected processors
> > + on - (default) selects IBPB or BHB clear
> > + mitigation based on CPU
>
> Is the "(default)" label accurate here? The code default is
> VMSCAPE_MITIGATION_AUTO, not VMSCAPE_MITIGATION_ON:
>
> static enum vmscape_mitigations vmscape_mitigation __ro_after_init =
> IS_ENABLED(CONFIG_MITIGATION_VMSCAPE) ?
> VMSCAPE_MITIGATION_AUTO : VMSCAPE_MITIGATION_NONE;
>
> In vmscape_select_mitigation(), AUTO and ON take the same switch
> path for selecting between BHB clear and IBPB. But AUTO goes
> through this check first:
>
> if ((vmscape_mitigation == VMSCAPE_MITIGATION_AUTO) &&
> !should_mitigate_vuln(X86_BUG_VMSCAPE))
> vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
>
> ON skips that check, which is the whole point of this commit per
> the subject line ("override attack vector controls").
>
> A sysadmin reading "on (default)" would conclude that not passing
> any option gives the same behavior as vmscape=on, but the actual
> default respects attack vector controls while vmscape=on overrides
> them.
Thats a valid point. Updating the documentation as below:
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 1068569be5cf..98204d464477 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8381,8 +8381,10 @@ Kernel parameters
(IBPB) mitigation
force - force vulnerability detection even on
unaffected processors
- on - (default) selects IBPB or BHB clear
+ auto - (default) use IBPB or BHB clear
mitigation based on CPU
+ on - same as "auto", but override attack
+ vector control
vsyscall= [X86-64,EARLY]
Controls the behavior of vsyscalls (i.e. calls to
^ permalink raw reply related
* Re: [PATCH RFC v2 1/9] dt-bindings: iio: frequency: add ad9910
From: Conor Dooley @ 2026-03-19 17:25 UTC (permalink / raw)
To: rodrigo.alencar
Cc: linux-iio, devicetree, linux-kernel, linux-doc,
Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
David Lechner, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Jonathan Corbet, Shuah Khan
In-Reply-To: <20260318-ad9910-iio-driver-v2-1-e79f93becf11@analog.com>
[-- Attachment #1: Type: text/plain, Size: 7654 bytes --]
On Wed, Mar 18, 2026 at 05:56:01PM +0000, Rodrigo Alencar via B4 Relay wrote:
> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
>
> DT-bindings for AD9910, a 1 GSPS DDS with 14-bit DAC. It includes
> configurations for clocks, DAC current, reset and basic GPIO control.
>
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
> ---
> .../bindings/iio/frequency/adi,ad9910.yaml | 189 +++++++++++++++++++++
> MAINTAINERS | 7 +
> 2 files changed, 196 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> new file mode 100644
> index 000000000000..68eaefea3f5a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> @@ -0,0 +1,189 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/frequency/adi,ad9910.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Analog Devices AD9910 Direct Digital Synthesizer
> +
> +maintainers:
> + - Rodrigo Alencar <rodrigo.alencar@analog.com>
> +
> +description:
> + The AD9910 is a 1 GSPS direct digital synthesizer (DDS) with an integrated
> + 14-bit DAC. It features single tone mode with 8 configurable profiles,
> + a digital ramp generator, RAM control, OSK, and a parallel data port for
> + high-speed streaming.
> +
> + https://www.analog.com/en/products/ad9910.html
> +
> +properties:
> + compatible:
> + const: adi,ad9910
> +
> + reg:
> + maxItems: 1
> +
> + spi-max-frequency:
> + maximum: 70000000
> +
> + clocks:
> + minItems: 1
> + maxItems: 2
> + description:
> + First clock is always the reference clock (REF_CLK), while the second
> + clock is an optional synchronization clock (SYNC_IN).
This should be an items list, like:
items:
- description: foo
- description: bar
> +
> + clock-names:
> + oneOf:
> + - items:
> + - const: ref_clk
s/_clk//, not like it can be anything else!
> + - items:
> + - const: ref_clk
> + - const: sync_in
> +
> + '#clock-cells':
> + const: 1
> +
> + clock-output-names:
> + minItems: 1
> + maxItems: 3
> + items:
> + enum: [ sync_clk, pdclk, sync_out ]
I'd say same here, but then you've got some issues with differentiation,
so idk.
> +
> + interrupts:
> + minItems: 1
> + maxItems: 2
Items list here please, the -names property shouldn't be the only place
one can figure out what goes where.
> +
> + interrupt-names:
> + minItems: 1
> + maxItems: 2
> + items:
> + enum: [ drover, ram_swp_ovr ]
> +
> + dvdd-io33-supply:
> + description: 3.3V Digital I/O supply.
> +
> + avdd33-supply:
> + description: 3.3V Analog DAC supply.
> +
> + dvdd18-supply:
> + description: 1.8V Digital Core supply.
> +
> + avdd18-supply:
> + description: 1.8V Analog Core supply.
> +
> + reset-gpios:
> + description:
> + GPIOs controlling the Main Device reset.
> +
> + io-reset-gpios:
> + maxItems: 1
> + description:
> + GPIO controlling the I/O_RESET pin.
> +
> + powerdown-gpios:
> + maxItems: 1
> + description:
> + GPIO controlling the EXT_PWR_DWN pin.
> +
> + update-gpios:
> + maxItems: 1
> + description:
> + GPIO controlling the I/O_UPDATE pin.
> +
> + profile-gpios:
> + minItems: 3
> + maxItems: 3
> + description:
> + GPIOs controlling the PROFILE[2:0] pins for profile selection.
> +
> + sync-err-gpios:
> + maxItems: 1
> + description:
> + GPIO used to read SYNC_SMP_ERR pin status.
> +
> + adi,pll-enable:
> + type: boolean
> + description:
> + Indicates that a loop filter is connected and the internal PLL is enabled.
> + Often used when the reference clock is provided by a crystal or by a
> + single-ended on-board oscillator.
> +
> + adi,charge-pump-current-microamp:
> + minimum: 212
> + maximum: 387
> + default: 387
> + description:
> + PLL charge pump current in microamps. Only applicable when the internal
> + PLL is enabled. The value is rounded to the nearest supported step. This
> + value depends mostly on the loop filter design.
> +
> + adi,refclk-out-drive-strength:
> + $ref: /schemas/types.yaml#/definitions/string
> + enum: [ disabled, low, medium, high ]
> + default: disabled
> + description:
> + Reference clock output (DRV0) drive strength. Only applicable when
> + the internal PLL is enabled.
> +
> + adi,dac-output-current-microamp:
> + minimum: 8640
> + maximum: 31590
> + default: 20070
> + description:
> + DAC full-scale output current in microamps.
> +
> +dependencies:
> + adi,charge-pump-current-microamp: [ 'adi,pll-enable' ]
> + adi,refclk-out-drive-strength: [ 'adi,pll-enable' ]
> + interrupts: [ interrupt-names ]
> + clocks: [ clock-names ]
> + '#clock-cells': [ clock-output-names ]
> +
> +required:
> + - compatible
> + - reg
> + - clocks
Worth pointing out, you haven't made either clock-names or
interrupt-names (when interrupts are used) mandatory, so the properties
cannot be used by a driver. I suggest you make clock-names mandatory and
interrupts depend on interrupt-names.
pw-bot: changes-requested
Cheers,
Conor.
> + - dvdd-io33-supply
> + - avdd33-supply
> + - dvdd18-supply
> + - avdd18-supply
> +
> +allOf:
> + - $ref: /schemas/spi/spi-peripheral-props.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + dds@0 {
> + compatible = "adi,ad9910";
> + reg = <0>;
> + spi-max-frequency = <1000000>;
> + clocks = <&ad9910_refclk>;
> + clock-names = "ref_clk";
> +
> + dvdd-io33-supply = <&vdd_io33>;
> + avdd33-supply = <&vdd_a33>;
> + dvdd18-supply = <&vdd_d18>;
> + avdd18-supply = <&vdd_a18>;
> +
> + reset-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
> + io-reset-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
> + powerdown-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
> + update-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
> + profile-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>,
> + <&gpio 5 GPIO_ACTIVE_HIGH>,
> + <&gpio 6 GPIO_ACTIVE_HIGH>;
> +
> + adi,pll-enable;
> + adi,charge-pump-current-microamp = <387>;
> + adi,refclk-out-drive-strength = "disabled";
> + };
> + };
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 08d8ddf4ef68..2ca8b68e5daa 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1630,6 +1630,13 @@ W: https://ez.analog.com/linux-software-drivers
> F: Documentation/devicetree/bindings/iio/dac/adi,ad9739a.yaml
> F: drivers/iio/dac/ad9739a.c
>
> +ANALOG DEVICES INC AD9910 DRIVER
> +M: Rodrigo Alencar <rodrigo.alencar@analog.com>
> +L: linux-iio@vger.kernel.org
> +S: Supported
> +W: https://ez.analog.com/linux-software-drivers
> +F: Documentation/devicetree/bindings/iio/frequency/adi,ad9910.yaml
> +
> ANALOG DEVICES INC MAX22007 DRIVER
> M: Janani Sunil <janani.sunil@analog.com>
> L: linux-iio@vger.kernel.org
>
> --
> 2.43.0
>
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 10/22] vfio/pci: Skip reset of preserved device after Live Update
From: David Matlack @ 2026-03-19 17:23 UTC (permalink / raw)
To: Jacob Pan
Cc: Alex Williamson, Adithya Jayachandran, Alexander Graf,
Alex Mastro, Alistair Popple, Andrew Morton, Ankit Agrawal,
Bjorn Helgaas, Chris Li, David Rientjes, Jason Gunthorpe,
Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Kevin Tian, kexec,
kvm, Leon Romanovsky, Leon Romanovsky, linux-doc, linux-kernel,
linux-kselftest, linux-mm, linux-pci, Lukas Wunner,
Michał Winiarski, Mike Rapoport, Parav Pandit,
Pasha Tatashin, Pranjal Shrivastava, Pratyush Yadav,
Raghavendra Rao Ananta, Rodrigo Vivi, Saeed Mahameed,
Samiullah Khawaja, Shuah Khan, Thomas Hellström,
Tomita Moeko, Vipin Sharma, Vivek Kasireddy, William Tu, Yi Liu,
Zhu Yanjun
In-Reply-To: <20260319093932.000078c2@linux.microsoft.com>
On Thu, Mar 19, 2026 at 9:39 AM Jacob Pan <jacob.pan@linux.microsoft.com> wrote:
>
> Hi David,
>
> On Mon, 16 Mar 2026 11:11:20 -0700
> David Matlack <dmatlack@google.com> wrote:
>
> > On Fri, Mar 13, 2026 at 8:39 AM Jacob Pan
> > <jacob.pan@linux.microsoft.com> wrote:
> > > On Thu, 12 Mar 2026 23:39:45 +0000
> > > David Matlack <dmatlack@google.com> wrote:
> >
> > > > +config VFIO_PCI_LIVEUPDATE
> > > > + bool "VFIO PCI support for Live Update (EXPERIMENTAL)"
> > > > + depends on LIVEUPDATE && VFIO_PCI
> > > > + help
> > > > + Support for preserving devices bound to vfio-pci across
> > > > a Live
> > > > + Update. The eventual goal is that preserved devices can
> > > > run
> > > > + uninterrupted during a Live Update, including DMA to
> > > > preserved
> > > > + memory buffers and P2P. However there are many steps
> > > > still needed to
> > > > + achieve this, including:
> > > > +
> > > > + - Preservation of iommufd files
> > > > + - Preservation of IOMMU driver state
> > > In the interim, what do you think about moving forward with noiommu
> > > mode without preserving IOMMU driver state?
> >
> > I haven't gotten a chance to look at your noiommu patches yet, but I
> > do think noiommu will probably be a good way to develop the VFIO and
> > PCI support for Live Update without blocking on IOMMU driver support.
> >
> > > I’ve tested your
> > > vfio_pci_liveupdate_kexec_test with the noiommu cdev, and it works
> > > as expected.
> >
> > Would you be able to send patches to add noiommu support to VFIO
> > selftests? That would be very helpful toward allowing us to develop
> > and test Live Update support with noiommu.
>
> It is included in the noiommu patchset; the only difference is that the
> VFIO cdev name is prefixed with noiommu, which is not strictly required
> and is done out of caution.
>
> /dev/vfio/
> |-- devices
> | `-- noiommu-vfio0
>
> https://lore.kernel.org/linux-iommu/20260312155637.376854-10-jacob.pan@linux.microsoft.com/
This one flew under my radar. I will take a look and respond there, thanks!
^ permalink raw reply
* Re: [PATCH v7 07/10] x86/vmscape: Use static_call() for predictor flush
From: bot+bpf-ci @ 2026-03-19 16:56 UTC (permalink / raw)
To: pawan.kumar.gupta, x86, nik.borisov, hpa, jpoimboe, david.kaplan,
seanjc, bp, dave.hansen, peterz, ast, daniel, andrii, kpsingh,
jolsa, davem, david.laight.linux, luto, tglx, mingo, dsahern,
martin.lau, eddyz87, song, yonghong.song, john.fastabend, sdf,
haoluo, pbonzini, corbet
Cc: linux-kernel, kvm, asit.k.mallick, tao1.zhang, bpf, netdev,
linux-doc, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260319-vmscape-bhb-v7-7-b76a777a98af@linux.intel.com>
[-- Attachment #1: Type: text/plain, Size: 1352 bytes --]
> diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
> index 68e2df3e3bf58..b75eda114503a 100644
> --- a/arch/x86/kernel/cpu/bugs.c
> +++ b/arch/x86/kernel/cpu/bugs.c
> @@ -144,6 +144,17 @@ EXPORT_SYMBOL_GPL(cpu_buf_idle_clear);
> */
> DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
>
> +/*
> + * Controls CPU Fill buffer clear before VMenter. This is a subset of
> + * X86_FEATURE_CLEAR_CPU_BUF, and should only be enabled when KVM-only
> + * mitigation is required.
> + */
> +DEFINE_STATIC_KEY_FALSE(cpu_buf_vm_clear);
> +EXPORT_SYMBOL_GPL(cpu_buf_vm_clear);
cpu_buf_vm_clear is defined and exported here but appears to have no
users. There is no declaration in any header, and nothing in this
patch series references it.
The comment describes CPU fill buffer clearing before VMenter, which
seems unrelated to the predictor flush static_call conversion that
this patch is doing. Was this included by mistake, or is it intended
for a follow-up series?
> +
> +DEFINE_STATIC_CALL_NULL(vmscape_predictor_flush, write_ibpb);
> +EXPORT_STATIC_CALL_GPL(vmscape_predictor_flush);
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23303796353
^ permalink raw reply
* Re: [PATCH v13 1/1] rust: interop: Add list module for C linked list interface
From: Joel Fernandes @ 2026-03-19 16:56 UTC (permalink / raw)
To: Gary Guo, Danilo Krummrich
Cc: linux-kernel, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Alex Gaynor, Dave Airlie, David Airlie, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Simona Vetter, Daniel Almeida,
Koen Koning, Nikola Djukic, Alexandre Courbot, Philipp Stanner,
Elle Rhumsaa, Jonathan Corbet, Alex Deucher, Christian König,
Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin,
Huang Rui, Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, John Hubbard,
Alistair Popple, Timur Tabi, Edwin Peer, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, alexeyi, Eliot Courtney,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev
In-Reply-To: <DH6R6GB10S07.AG2EY39F0P85@garyguo.net>
On 3/19/2026 8:21 AM, Gary Guo wrote:
> On Thu Mar 19, 2026 at 12:05 PM GMT, Danilo Krummrich wrote:
>> On Thu Mar 19, 2026 at 12:39 PM CET, Gary Guo wrote:
>>> On Tue Mar 17, 2026 at 8:17 PM GMT, Joel Fernandes wrote:
>>>> Add a new module `kernel::interop::list` for working with C's doubly
>>>> circular linked lists. Provide low-level iteration over list nodes.
>>>>
>>>> Typed iteration over actual items is provided with a `clist_create`
>>>> macro to assist in creation of the `CList` type.
>>>>
>>>> Cc: Nikola Djukic <ndjukic@nvidia.com>
>>>> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
>>>> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
>>>> Acked-by: Alexandre Courbot <acourbot@nvidia.com>
>>>> Acked-by: Gary Guo <gary@garyguo.net>
>>>> Acked-by: Miguel Ojeda <ojeda@kernel.org>
>>>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>>>> ---
>>>> MAINTAINERS | 8 +
>>>> rust/helpers/helpers.c | 1 +
>>>> rust/helpers/list.c | 17 ++
>>>> rust/kernel/interop.rs | 9 +
>>>> rust/kernel/interop/list.rs | 342 ++++++++++++++++++++++++++++++++++++
>>>> rust/kernel/lib.rs | 2 +
>>>> 6 files changed, 379 insertions(+)
>>>> create mode 100644 rust/helpers/list.c
>>>> create mode 100644 rust/kernel/interop.rs
>>>> create mode 100644 rust/kernel/interop/list.rs
>>>>
>>>> +/// Create a C doubly-circular linked list interface [`CList`] from a raw `list_head` pointer.
>>>> +///
>>>> +/// This macro creates a `CList<T, OFFSET>` that can iterate over items of type `$rust_type`
>>>> +/// linked via the `$field` field in the underlying C struct `$c_type`.
>>>> +///
>>>> +/// # Arguments
>>>> +///
>>>> +/// - `$head`: Raw pointer to the sentinel `list_head` object (`*mut bindings::list_head`).
>>>> +/// - `$rust_type`: Each item's rust wrapper type.
>>>> +/// - `$c_type`: Each item's C struct type that contains the embedded `list_head`.
>>>> +/// - `$field`: The name of the `list_head` field within the C struct.
>>>> +///
>>>> +/// # Safety
>>>> +///
>>>> +/// The caller must ensure:
>>>> +///
>>>> +/// - `$head` is a valid, initialized sentinel `list_head` (e.g. via `INIT_LIST_HEAD()`)
>>>> +/// pointing to a list that is not concurrently modified for the lifetime of the [`CList`].
>>>> +/// - The list contains items of type `$c_type` linked via an embedded `$field`.
>>>> +/// - `$rust_type` is `#[repr(transparent)]` over `$c_type` or has compatible layout.
>>>> +///
>>>> +/// # Examples
>>>> +///
>>>> +/// Refer to the examples in the [`crate::interop::list`] module documentation.
>>>> +#[macro_export]
>>>> +macro_rules! clist_create {
>>>> + (unsafe { $head:ident, $rust_type:ty, $c_type:ty, $($field:tt).+ }) => {{
>>>> + // Compile-time check that field path is a `list_head`.
>>>> + // SAFETY: `p` is a valid pointer to `$c_type`.
>>>> + let _: fn(*const $c_type) -> *const $crate::bindings::list_head =
>>>> + |p| unsafe { &raw const (*p).$($field).+ };
>>>
>>> Actually, this check is insufficient, you should create a reference instead
>>> (just in case people put this inside `repr(packed)`.
>>>
>>> This could be something like
>>>
>>> let _ = |p: &$c_type| { _ = &p.$($field).+ }
>>>
>>> ?
>>>
>>>> +
>>>> + // Calculate offset and create `CList`.
>>>> + const OFFSET: usize = ::core::mem::offset_of!($c_type, $($field).+);
>>>> + // SAFETY: The caller of this macro is responsible for ensuring safety.
>>>> + unsafe { $crate::interop::list::CList::<$rust_type, OFFSET>::from_raw($head) }
>>>
>>> Given that this is unsafe, I am not sure why the macro should have unsafe
>>> keyword in it, rather than just being `clist_create(a, b, c, d)` and just have
>>> user write unsafe.
>>
>> Either you are proposing to not wrap unsafe code within unsafe {} within the
>> macro, such that the user is forced to write an unsafe {} around the macro, but
>> then they calls within the macro are not justified individually, or you propose
>> to let the user write an unsafe {} around the macro regardless of the inner
>> unsafe {} blocks, but then then the compiler warns about an unnecessary unsafe
>> and nothing forces the user to actually wrap it in unsafe {}.
>
> The former.
>
> "The caller of this macro is responsible for ensuring safety" justification is
> not really useful here IMO.
>
> If there're cases where we do want to justify unsafe code that's not immediately
> deferring to the user inside the macro, we could use the SAFETY* trick proposed
> in the thread, without writing an actual `unsafe {}` block.
>
>>
>> Is there a third option I'm not aware of? I.e. for the above reason
>> impl_device_context_deref!() was designed the same way.
>
> impl_device_context_deref!() expands to an item, so the user couldn't put an
> `unsafe {}` on the outside. This macro expands to an expression, so users can
> add `unsafe` themselves.
>
I like Gary's idea. I will drop the unsafe { } blocks within the macro and
we can force the caller to clear the lint. That's the cleanest and most
reasonable IMO, instead of working around the linter.
Unless someone yells, this is what I'll do for the next iteration.
--
Joel Fernandes
^ permalink raw reply
* Re: [PATCH v3 2/4] kallsyms: extend lineinfo to loadable modules
From: Sasha Levin @ 2026-03-19 16:43 UTC (permalink / raw)
To: Petr Pavlu
Cc: Andrew Morton, Masahiro Yamada, Luis Chamberlain, Linus Torvalds,
Richard Weinberger, Juergen Gross, Geert Uytterhoeven,
James Bottomley, Jonathan Corbet, Nathan Chancellor,
Nicolas Schier, Daniel Gomez, Greg KH, Petr Mladek,
Steven Rostedt, Kees Cook, Peter Zijlstra, Thorsten Leemhuis,
Vlastimil Babka, Helge Deller, Randy Dunlap, Laurent Pinchart,
Vivian Wang, linux-kernel, linux-kbuild, linux-modules, linux-doc
In-Reply-To: <79244e56-b3ea-4986-b4a2-91a78b21bf07@suse.com>
Thanks for the great review!
On Thu, Mar 19, 2026 at 11:37:18AM +0100, Petr Pavlu wrote:
>On 3/12/26 4:06 AM, Sasha Levin wrote:
>> +- **No init text**: For modules, functions in ``.init.text`` are not annotated
>> + because that memory is freed after module initialization.
>
>A second table .init.mod_lineinfo could be added to provide the
>necessary information for .init sections, which would be dropped along
>with all the other init code+data.
Sure, it's something we can look at it later. For this series I'd like to keep
scope to runtime .text, since init code runs briefly and rarely appears in
stack traces that need debugging. Adding a second section would require module
loader changes for loading and freeing it alongside init memory.
>> --- /dev/null
>> +++ b/include/linux/mod_lineinfo.h
>> @@ -0,0 +1,68 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * mod_lineinfo.h - Binary format for per-module source line information
>> + *
>> + * This header defines the layout of the .mod_lineinfo section embedded
>> + * in loadable kernel modules. It is dual-use: included from both the
>> + * kernel and the userspace gen_lineinfo tool.
>> + *
>> + * Section layout (all values in target-native endianness):
>> + *
>> + * struct mod_lineinfo_header (16 bytes)
>> + * u32 addrs[num_entries] -- offsets from .text base, sorted
>
>Modules are relocatable objects. The typical way to express a reference
>from one section to data in another section is to use relocations.
>Choosing to use an implicit base and resolved offsets means that the
>code has trouble correctly referencing the .text section and can't
>express line information data for other sections, such as .exit.text.
I agree, which is why I scoped this just to .text :)
My thinking was that using ELF relocations would add significant complexity to
both the build tool and the runtime lookup path, which must remain NMI-safe and
allocation-free.
>> + * u16 file_ids[num_entries] -- parallel to addrs
>> + * <2-byte pad if num_entries is odd>
>> + * u32 lines[num_entries] -- parallel to addrs
>> + * u32 file_offsets[num_files] -- byte offset into filenames[]
>> + * char filenames[filenames_size] -- concatenated NUL-terminated strings
>
>Nit: The description could be a bit easier to navigate if the
>mod_lineinfo_header struct was expanded, so it is clear where
>num_entries, num_files and filenames_size come from.
Makes sense
>> + */
>> +#ifndef _LINUX_MOD_LINEINFO_H
>> +#define _LINUX_MOD_LINEINFO_H
>> +
>> +#ifdef __KERNEL__
>> +#include <linux/types.h>
>> +#else
>> +#include <stdint.h>
>> +typedef uint32_t u32;
>> +typedef uint16_t u16;
>> +#endif
>> +
>> +struct mod_lineinfo_header {
>> + u32 num_entries;
>> + u32 num_files;
>> + u32 filenames_size; /* total bytes of concatenated filenames */
>
>An alternative would be to say that the filenames data extends to the
>end of the section, without requiring an explicit filenames_size.
I'd prefer to keep filenames_size explicit: it allows lineinfo_search() to
validate filename offsets without knowing the section size. This keeps the
search function reusable between vmlinux (where data comes from linker globals
with no "section size") and modules (where it comes from a section). The cost
is 4 bytes per module.
>> + u32 reserved; /* padding, must be 0 */
>
>I believe the format should remain internal to the kernel, so there is
>no need for such a reserved member.
The format is indeed internal and we don't generally concern ourselves with
out-of-tree modules. I've originally added it as a minimal safety net: if the
format ever changes and a stale .ko with an old-format .mod_lineinfo gets
loaded, the kernel would silently misparse lineinfo data.
I don't feel too strongly about it either way, but 4 bytes felt a pretty cheap
price to pay for this safety net :)
>> +static inline u32 mod_lineinfo_lines_off(u32 num_entries)
>> +{
>> + /* u16 file_ids[] may need 2-byte padding to align lines[] to 4 bytes */
>> + u32 off = mod_lineinfo_file_ids_off(num_entries) +
>> + num_entries * sizeof(u16);
>> + return (off + 3) & ~3u;
>> +}
>> +
>> +static inline u32 mod_lineinfo_file_offsets_off(u32 num_entries)
>> +{
>> + return mod_lineinfo_lines_off(num_entries) + num_entries * sizeof(u32);
>> +}
>> +
>> +static inline u32 mod_lineinfo_filenames_off(u32 num_entries, u32 num_files)
>> +{
>> + return mod_lineinfo_file_offsets_off(num_entries) +
>> + num_files * sizeof(u32);
>> +}
>
>These helpers are used only from kernel/module/kallsyms.c. I assume they
>are present in this header file to stay close to the description of the
>format.
>
>I personally find them quite verbose. The module_lookup_lineinfo()
>function needs an intimate knowledge of the data format anyway. The code
>in module_lookup_lineinfo() could be replaced with just:
>
> addrs = base + sizeof(struct mod_lineinfo_header);
> file_ids = addrs + num_entries * sizeof(u32);
> lines = (file_ids + num_entries * sizeof(u16) + 3) & ~3u;
> file_offsets = lines + num_entries * sizeof(u32);
> filenames = file_offsets + num_files * sizeof(u32);
They are very verbose mostly to make it easy for me to understand :)
Note that the next patch which adds compression rewrites these completely.
I kept these here just to make it easier to understand what's happening during
my development work as well as reviews.
>> +
>> +#endif /* _LINUX_MOD_LINEINFO_H */
>> diff --git a/include/linux/module.h b/include/linux/module.h
>> index 14f391b186c6d..d23e0cd9c7210 100644
>> --- a/include/linux/module.h
>> +++ b/include/linux/module.h
>> @@ -508,6 +508,8 @@ struct module {
>> void *btf_data;
>> void *btf_base_data;
>> #endif
>> + void *lineinfo_data; /* .mod_lineinfo section in MOD_RODATA */
>> + unsigned int lineinfo_data_size;
>
>The lineinfo-specific members should be enclosed within the `#ifdef
>CONFIG_KALLSYMS_LINEINFO_MODULES`.
>
>This will require module_lookup_lineinfo() to be conditionally compiled
>based on CONFIG_KALLSYMS_LINEINFO_MODULES, with a dummy version provided
>otherwise. Alternatively, accessors to module::lineinfo_data and
>module::lineinfo_data_size that handle CONFIG_KALLSYMS_LINEINFO_MODULES
>could be introduced in include/linux/module.h. For example, see
>module_buildid() or is_livepatch_module.
The struct members were deliberately left without #ifdef guards following Helge
Deller's suggestion in the v1 review[1]. I don't really mind either way, but
I'd prefer to have a consensus before flipping it back and forth.
Helge?
[1] https://lore.kernel.org/all/3ab0cad6-bf55-4ae5-afb7-d9129ac2032e@gmx.de/
>> + addrs = base + mod_lineinfo_addrs_off();
>> + file_ids = base + mod_lineinfo_file_ids_off(num_entries);
>> + lines = base + mod_lineinfo_lines_off(num_entries);
>> + file_offsets = base + mod_lineinfo_file_offsets_off(num_entries);
>> + filenames = base + mod_lineinfo_filenames_off(num_entries, num_files);
>> +
>> + /* Compute offset from module .text base */
>> + text_base = (unsigned long)mod->mem[MOD_TEXT].base;
>
>The module::mem[] covers module memory regions. One can think of them as
>ELF segments, except they are created dynamically by the module loader.
>The code conflates the .text section and the TEXT segment. I'm not aware
>of any guarantee that the .text section will be always placed as the
>first section in this segment.
You're right that this conflates section and segment. In practice, .text is
always first in MOD_TEXT because __layout_sections() processes SHF_EXECINSTR
sections in ELF order, and .text is conventionally first. But I agree this
shouldn't be an implicit assumption.
We can add a validation check at module load time to verify the assumption
for now, and address it better when ...
>Relocations can be used to accurately reference the .text section.
... we add full relocation support.
>> + if (addr < text_base)
>> + return false;
>> +
>> + raw_offset = addr - text_base;
>> + if (raw_offset > UINT_MAX)
>
>The offsets in the addrs array are of the u32 type, so this should be
>strictly speaking checked against U32_MAX.
Right
>> --- a/scripts/Makefile
>> +++ b/scripts/Makefile
>> @@ -5,6 +5,7 @@
>>
>> hostprogs-always-$(CONFIG_KALLSYMS) += kallsyms
>> hostprogs-always-$(CONFIG_KALLSYMS_LINEINFO) += gen_lineinfo
>> +hostprogs-always-$(CONFIG_KALLSYMS_LINEINFO_MODULES) += gen_lineinfo
>
>This line is unnecessary because CONFIG_KALLSYMS_LINEINFO_MODULES
>depends on CONFIG_KALLSYMS_LINEINFO.
It is. I mostly left it here for clarity's sake. I'll drop it.
>> @@ -59,6 +62,9 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
>> +$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
>> ifdef CONFIG_DEBUG_INFO_BTF_MODULES
>> +$(if $(newer-prereqs),$(call cmd,btf_ko))
>> +endif
>> +ifdef CONFIG_KALLSYMS_LINEINFO_MODULES
>> + +$(if $(newer-prereqs),$(call cmd,lineinfo_ko))
>
>Should this be 'if_changed_except.. vmlinux'?
Lineinfo generation doesn't depend on vmlinux - it reads DWARF directly from
the .ko file itself. Unlike BTF (which uses vmlinux as a base for
deduplication), there's no vmlinux prerequisite to exclude.
>> @@ -194,9 +200,45 @@ static const char *make_relative(const char *path, const char *comp_dir)
>> return p ? p + 1 : path;
>> }
>>
>> - /* Fall back to basename */
>> - p = strrchr(path, '/');
>> - return p ? p + 1 : path;
>> + /*
>> + * Relative path — check for duplicated-path quirk from libdw
>> + * on ET_REL files (e.g., "a/b.c/a/b.c" → "a/b.c").
>> + */
>
>When does this quirk occur? Is it a bug in libdw?
This occurs with elfutils libdw when processing ET_REL .ko files. libdw
constructs source paths by concatenating DW_AT_comp_dir with DW_AT_name from
the compilation unit. For modules where both are relative paths with the same
prefix, this can produce doubled results like "net/foo/bar.c/net/foo/bar.c". It
appears to be a libdw quirk with ET_REL DWARF handling.
>> + {
>> + size_t len = strlen(path);
>> +
>> + for (p = path; (p = strchr(p, '/')) != NULL; p++) {
>> + size_t prefix = p - path;
>> + size_t rest = len - prefix - 1;
>> +
>> + if (rest == prefix && !memcmp(path, p + 1, prefix))
>> + return p + 1;
>> + }
>
>Isn't this loop same as:
>
>size_t mid = len / 2;
>if (path[mid] == '/' && !memcmp(path, path + mid + 1, mid - 1))
> return path + mid + 1;
I think so! For a true duplication "X/X", the split is always at the exact
midpoint (len/2), so the loop over every '/' is unnecessary. I'll adopt this
approach with the memcmp length as `mid` rather than `mid - 1` to compare the
full second half.
>> +static unsigned int r_type_abs32(unsigned int e_machine)
>> +{
>> + switch (e_machine) {
>> + case EM_X86_64: return 10; /* R_X86_64_32 */
>> + case EM_386: return 1; /* R_386_32 */
>> + case EM_AARCH64: return 258; /* R_AARCH64_ABS32 */
>> + case EM_ARM: return 2; /* R_ARM_ABS32 */
>> + case EM_RISCV: return 1; /* R_RISCV_32 */
>> + case EM_S390: return 4; /* R_390_32 */
>> + case EM_MIPS: return 2; /* R_MIPS_32 */
>> + case EM_PPC64: return 1; /* R_PPC64_ADDR32 */
>> + case EM_PPC: return 1; /* R_PPC_ADDR32 */
>> + case EM_LOONGARCH: return 1; /* R_LARCH_32 */
>> + case EM_PARISC: return 1; /* R_PARISC_DIR32 */
>> + default: return 0;
>
>The source file already includes elf.h from elfutils. Is it necessary to
>hardcode these relocation values here?
Right!
>> static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
>> {
>> Dwarf_Off off = 0, next_off;
>> @@ -295,6 +490,16 @@ static void process_dwarf(Dwarf *dwarf, unsigned long long text_addr)
>> if (addr < text_addr)
>> continue;
>>
>> + /*
>> + * In module mode, keep only .text addresses.
>> + * In ET_REL .ko files, .init.text/.exit.text may
>> + * overlap with .text address ranges, so we must
>> + * explicitly check against the .text bounds.
>> + */
>
>Nit: The use of "may" in this comment seems strange. It is fully
>expected that .text, .init.text, .exit.text or any other section will
>have their sh_addr set to 0 in relocatable objects and therefore the
>sections have overlapping address ranges.
I guess I wasn't sure if it's really always the case. We can adjust the comment.
>> + if (module_mode && text_section_end > text_section_start &&
>> + (addr < text_section_start || addr >= text_section_end))
>> + continue;
>> +
>
>The current code is very specific to the .text section. It would be good
>to cover all sections in the future. I think it will naturally require
>use of relocations to refer to individual sections.
Yup, we can definitely give it a go in the future.
--
Thanks,
Sasha
^ permalink raw reply
* Re: [PATCH v7 10/10] x86/vmscape: Add cmdline vmscape=on to override attack vector controls
From: bot+bpf-ci @ 2026-03-19 16:40 UTC (permalink / raw)
To: pawan.kumar.gupta, x86, nik.borisov, hpa, jpoimboe, david.kaplan,
seanjc, bp, dave.hansen, peterz, ast, daniel, andrii, kpsingh,
jolsa, davem, david.laight.linux, luto, tglx, mingo, dsahern,
martin.lau, eddyz87, song, yonghong.song, john.fastabend, sdf,
haoluo, pbonzini, corbet
Cc: linux-kernel, kvm, asit.k.mallick, tao1.zhang, bpf, netdev,
linux-doc, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260319-vmscape-bhb-v7-10-b76a777a98af@linux.intel.com>
[-- Attachment #1: Type: text/plain, Size: 1755 bytes --]
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -8375,9 +8375,11 @@
>
> off - disable the mitigation
> ibpb - use Indirect Branch Prediction Barrier
> - (IBPB) mitigation (default)
> + (IBPB) mitigation
> force - force vulnerability detection even on
> unaffected processors
> + on - (default) selects IBPB or BHB clear
> + mitigation based on CPU
Is the "(default)" label accurate here? The code default is
VMSCAPE_MITIGATION_AUTO, not VMSCAPE_MITIGATION_ON:
static enum vmscape_mitigations vmscape_mitigation __ro_after_init =
IS_ENABLED(CONFIG_MITIGATION_VMSCAPE) ?
VMSCAPE_MITIGATION_AUTO : VMSCAPE_MITIGATION_NONE;
In vmscape_select_mitigation(), AUTO and ON take the same switch
path for selecting between BHB clear and IBPB. But AUTO goes
through this check first:
if ((vmscape_mitigation == VMSCAPE_MITIGATION_AUTO) &&
!should_mitigate_vuln(X86_BUG_VMSCAPE))
vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
ON skips that check, which is the whole point of this commit per
the subject line ("override attack vector controls").
A sysadmin reading "on (default)" would conclude that not passing
any option gives the same behavior as vmscape=on, but the actual
default respects attack vector controls while vmscape=on overrides
them.
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23303796353
^ permalink raw reply
* Re: [PATCH v2 10/22] vfio/pci: Skip reset of preserved device after Live Update
From: Jacob Pan @ 2026-03-19 16:39 UTC (permalink / raw)
To: David Matlack
Cc: Alex Williamson, Adithya Jayachandran, Alexander Graf,
Alex Mastro, Alistair Popple, Andrew Morton, Ankit Agrawal,
Bjorn Helgaas, Chris Li, David Rientjes, Jason Gunthorpe,
Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Kevin Tian, kexec,
kvm, Leon Romanovsky, Leon Romanovsky, linux-doc, linux-kernel,
linux-kselftest, linux-mm, linux-pci, Lukas Wunner,
Michał Winiarski, Mike Rapoport, Parav Pandit,
Pasha Tatashin, Pranjal Shrivastava, Pratyush Yadav,
Raghavendra Rao Ananta, Rodrigo Vivi, Saeed Mahameed,
Samiullah Khawaja, Shuah Khan, Thomas Hellström,
Tomita Moeko, Vipin Sharma, Vivek Kasireddy, William Tu, Yi Liu,
Zhu Yanjun
In-Reply-To: <CALzav=eGLpo5nrsHq5L8bUTC=FWZ-SgrTE1FoScrWB4p+NDgnA@mail.gmail.com>
Hi David,
On Mon, 16 Mar 2026 11:11:20 -0700
David Matlack <dmatlack@google.com> wrote:
> On Fri, Mar 13, 2026 at 8:39 AM Jacob Pan
> <jacob.pan@linux.microsoft.com> wrote:
> > On Thu, 12 Mar 2026 23:39:45 +0000
> > David Matlack <dmatlack@google.com> wrote:
>
> > > +config VFIO_PCI_LIVEUPDATE
> > > + bool "VFIO PCI support for Live Update (EXPERIMENTAL)"
> > > + depends on LIVEUPDATE && VFIO_PCI
> > > + help
> > > + Support for preserving devices bound to vfio-pci across
> > > a Live
> > > + Update. The eventual goal is that preserved devices can
> > > run
> > > + uninterrupted during a Live Update, including DMA to
> > > preserved
> > > + memory buffers and P2P. However there are many steps
> > > still needed to
> > > + achieve this, including:
> > > +
> > > + - Preservation of iommufd files
> > > + - Preservation of IOMMU driver state
> > In the interim, what do you think about moving forward with noiommu
> > mode without preserving IOMMU driver state?
>
> I haven't gotten a chance to look at your noiommu patches yet, but I
> do think noiommu will probably be a good way to develop the VFIO and
> PCI support for Live Update without blocking on IOMMU driver support.
>
> > I’ve tested your
> > vfio_pci_liveupdate_kexec_test with the noiommu cdev, and it works
> > as expected.
>
> Would you be able to send patches to add noiommu support to VFIO
> selftests? That would be very helpful toward allowing us to develop
> and test Live Update support with noiommu.
It is included in the noiommu patchset; the only difference is that the
VFIO cdev name is prefixed with noiommu, which is not strictly required
and is done out of caution.
/dev/vfio/
|-- devices
| `-- noiommu-vfio0
https://lore.kernel.org/linux-iommu/20260312155637.376854-10-jacob.pan@linux.microsoft.com/
^ permalink raw reply
* Re: [PATCH v2 06/16] mm: add mmap_action_simple_ioremap()
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 16:29 UTC (permalink / raw)
To: Suren Baghdasaryan
Cc: Andrew Morton, 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, Michal Hocko, Jann Horn, Pedro Falcato,
linux-kernel, linux-doc, linux-hyperv, linux-stm32,
linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <330f3614-7dc1-4e80-96c4-8472b25108bb@lucifer.local>
On Wed, Mar 18, 2026 at 08:39:25PM +0000, Lorenzo Stoakes (Oracle) wrote:
> On Mon, Mar 16, 2026 at 09:14:28PM -0700, Suren Baghdasaryan wrote:
> > > +int simple_ioremap_prepare(struct vm_area_desc *desc)
> > > +{
> > > + struct mmap_action *action = &desc->action;
> > > + const phys_addr_t start = action->simple_ioremap.start_phys_addr;
> > > + const unsigned long size = action->simple_ioremap.size;
> > > + unsigned long pfn;
> > > + int err;
> > > +
> > > + err = __simple_ioremap_prep(desc->start, desc->end, desc->pgoff,
> > > + start, size, &pfn);
> > > + if (err)
> > > + return err;
> > > +
> > > + /* The I/O remap logic does the heavy lifting. */
> > > + mmap_action_ioremap(desc, desc->start, pfn, vma_desc_size(desc));
> >
> > nit: Looks like a perfect opportunity to use mmap_action_ioremap_full() here.
>
> Yeah can do!
>
> >
> > > + return mmap_action_prepare(desc);
> >
> > Ok, so IIUC this uses recursion:
> > mmap_action_prepare(MMAP_SIMPLE_IO_REMAP) -> simple_ioremap_prepare()
> > -> mmap_action_prepare(MMAP_IO_REMAP_PFN).
>
> Yep, it's one level, I think that should be ok? :)
On second thoughts, it's silly not just to call io_remap_pfn_range_prepare()
direct so will change it to do that!
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH v2 10/22] vfio/pci: Skip reset of preserved device after Live Update
From: Jacob Pan @ 2026-03-19 16:28 UTC (permalink / raw)
To: Vipin Sharma
Cc: David Matlack, Alex Williamson, Adithya Jayachandran,
Alexander Graf, Alex Mastro, Alistair Popple, Andrew Morton,
Ankit Agrawal, Bjorn Helgaas, Chris Li, David Rientjes,
Jason Gunthorpe, Jason Gunthorpe, Jonathan Corbet, Josh Hilke,
Kevin Tian, kexec, kvm, Leon Romanovsky, Leon Romanovsky,
linux-doc, linux-kernel, linux-kselftest, linux-mm, linux-pci,
Lukas Wunner, Michał Winiarski, Mike Rapoport, Parav Pandit,
Pasha Tatashin, Pranjal Shrivastava, Pratyush Yadav,
Raghavendra Rao Ananta, Rodrigo Vivi, Saeed Mahameed,
Samiullah Khawaja, Shuah Khan, Thomas Hellström,
Tomita Moeko, Vivek Kasireddy, William Tu, Yi Liu, Zhu Yanjun
In-Reply-To: <20260316162518.GB1767448.vipinsh@google.com>
Hi Vipin,
On Mon, 16 Mar 2026 09:28:32 -0700
Vipin Sharma <vipinsh@google.com> wrote:
> On Fri, Mar 13, 2026 at 08:39:18AM -0700, Jacob Pan wrote:
> > Hi David,
> >
> > > +config VFIO_PCI_LIVEUPDATE
> > > + bool "VFIO PCI support for Live Update (EXPERIMENTAL)"
> > > + depends on LIVEUPDATE && VFIO_PCI
> > > + help
> > > + Support for preserving devices bound to vfio-pci across
> > > a Live
> > > + Update. The eventual goal is that preserved devices can
> > > run
> > > + uninterrupted during a Live Update, including DMA to
> > > preserved
> > > + memory buffers and P2P. However there are many steps
> > > still needed to
> > > + achieve this, including:
> > > +
> > > + - Preservation of iommufd files
> > > + - Preservation of IOMMU driver state
> > In the interim, what do you think about moving forward with noiommu
> > mode without preserving IOMMU driver state? I’ve tested your
> > vfio_pci_liveupdate_kexec_test with the noiommu cdev, and it works
> > as expected.
> >
>
> Just curious, are you using qemu VM without iommu device for noiommu
> work or do you have actual system without iommu hardware for testing?
I am using a qemu VM without iommu device and with an assigned
nvme device. I use a low level nvme userspace driver (modified to use
iommufd noiommu mode) for testing.
https://github.com/SamsungDS/libvfn
^ permalink raw reply
* Re: (subset) [PATCH v2 00/10] workqueue / drivers: Add device-managed allocate workqueue
From: Lee Jones @ 2026-03-19 16:21 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Jonathan Corbet, Shuah Khan, Tejun Heo, Lai Jiangshan,
Tobias Schrammm, Sebastian Reichel, Andy Shevchenko,
Dan Carpenter, Krzysztof Kozlowski, Lee Jones, Dzmitry Sankouski,
Matthias Brugger, AngeloGioacchino Del Regno, Benson Leung,
Tzung-Bi Shih, Krzysztof Kozlowski
Cc: Matti Vaittinen, driver-core, linux-doc, linux-kernel,
Sebastian Reichel, linux-pm, linux-arm-kernel, linux-mediatek,
chrome-platform, stable
In-Reply-To: <20260305-workqueue-devm-v2-0-66a38741c652@oss.qualcomm.com>
On Thu, 05 Mar 2026 22:45:39 +0100, Krzysztof Kozlowski wrote:
> Merging / Dependency
> ====================
> All further patches depend on the first one, thus this probably should
> go via one tree, e.g. power supply. The first patch might be needed for
> other trees as well, e.g. if more drivers are discovered, so the best if
> it is on dedicated branch in case it has to be shared.
>
> [...]
Applied, thanks!
[07/10] mfd: ezx-pcap: Drop memory allocation error message
commit: 33e0316783a205625b7c55a78041ddc0d5dce7c7
[08/10] mfd: ezx-pcap: Return directly instead of empty gotos
commit: 444e11d9d9e56c994da8a253cdf7f33ac2eeb15b
[09/10] mfd: ezx-pcap: Avoid rescheduling after destroying workqueue
commit: 356ee03f6ae7d04f90d8e2104660193c4f3a071c
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH net-next 06/15] libie: add bookkeeping support for control queue messages
From: Tony Nguyen @ 2026-03-19 16:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, pabeni, edumazet, andrew+netdev, netdev, Phani R Burra,
larysa.zaremba, przemyslaw.kitszel, aleksander.lobakin,
sridhar.samudrala, anjali.singhai, michal.swiatkowski,
maciej.fijalkowski, emil.s.tantilov, madhu.chittim, joshua.a.hay,
jacob.e.keller, jayaprakash.shanmugam, natalia.wochtman, jiri,
horms, corbet, richardcochran, linux-doc, Bharath R, Samuel Salin
In-Reply-To: <20260318193447.2e7b1f4d@kernel.org>
On 3/18/2026 7:34 PM, Jakub Kicinski wrote:
> On Tue, 17 Mar 2026 16:08:54 -0700 Tony Nguyen wrote:
>> From: Phani R Burra <phani.r.burra@intel.com>
>>
>> All send control queue messages are allocated/freed in libie itself and
>> tracked with the unique transaction (Xn) ids until they receive response or
>> time out. Responses can be received out of order, therefore transactions
>> are stored in an array and tracked though a bitmap.
>>
>> Pre-allocated DMA memory is used where possible. It reduces the driver
>> overhead in handling memory allocation/free and message timeouts.
>
> Warning: include/linux/intel/libie/controlq.h:397 struct member 'force' not described in 'libie_ctlq_xn_clean_params'
Will fix this
> Please also look thru the AI reviews before you repost:
> https://netdev-ai.bots.linux.dev/ai-review.html?id=2078570c-9d93-4076-ace9-f275d8637314
> and:
> https://sashiko.dev/#/patchset/20260317230905.847744-1-anthony.l.nguyen%40intel.com
and look these over and adjust as needed.
Thanks,
Tony
^ permalink raw reply
* Re: [PATCH mm-unstable v15 11/13] mm/khugepaged: avoid unnecessary mTHP collapse attempts
From: Lorenzo Stoakes (Oracle) @ 2026-03-19 15:59 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: Nico Pache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, lance.yang, Liam.Howlett, lorenzo.stoakes,
mathieu.desnoyers, matthew.brost, mhiramat, mhocko, peterx,
pfalcato, rakie.kim, raquini, rdunlap, richard.weiyang, rientjes,
rostedt, rppt, ryan.roberts, shivankg, sunnanyong, surenb,
thomas.hellstrom, tiwai, usamaarif642, vbabka, vishal.moola,
wangkefeng.wang, will, willy, yang, ying.huang, ziy, zokeefe
In-Reply-To: <4774da78-8349-4eda-a09b-7248e82cb26b@kernel.org>
On Wed, Mar 18, 2026 at 08:48:30PM +0100, David Hildenbrand (Arm) wrote:
> On 3/18/26 19:59, Nico Pache wrote:
> >
> >
> > On 3/17/26 4:35 AM, Lorenzo Stoakes (Oracle) wrote:
> >> On Wed, Feb 25, 2026 at 08:26:31PM -0700, Nico Pache wrote:
> >>> There are cases where, if an attempted collapse fails, all subsequent
> >>> orders are guaranteed to also fail. Avoid these collapse attempts by
> >>> bailing out early.
> >>>
> >>> Signed-off-by: Nico Pache <npache@redhat.com>
> >>
> >> With David's concern addressed:
> >>
> >> Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
> >>
> >>> ---
> >>> mm/khugepaged.c | 35 ++++++++++++++++++++++++++++++++++-
> >>> 1 file changed, 34 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> >>> index 1c3711ed4513..388d3f2537e2 100644
> >>> --- a/mm/khugepaged.c
> >>> +++ b/mm/khugepaged.c
> >>> @@ -1492,9 +1492,42 @@ static int mthp_collapse(struct mm_struct *mm, unsigned long address,
> >>> ret = collapse_huge_page(mm, collapse_address, referenced,
> >>> unmapped, cc, mmap_locked,
> >>> order);
> >>> - if (ret == SCAN_SUCCEED) {
> >>> +
> >>> + switch (ret) {
> >>> + /* Cases were we continue to next collapse candidate */
> >>> + case SCAN_SUCCEED:
> >>> collapsed += nr_pte_entries;
> >>> + fallthrough;
> >>> + case SCAN_PTE_MAPPED_HUGEPAGE:
> >>> continue;
> >>> + /* Cases were lower orders might still succeed */
> >>> + case SCAN_LACK_REFERENCED_PAGE:
> >>> + case SCAN_EXCEED_NONE_PTE:
> >>> + case SCAN_EXCEED_SWAP_PTE:
> >>> + case SCAN_EXCEED_SHARED_PTE:
> >>> + case SCAN_PAGE_LOCK:
> >>> + case SCAN_PAGE_COUNT:
> >>> + case SCAN_PAGE_LRU:
> >>> + case SCAN_PAGE_NULL:
> >>> + case SCAN_DEL_PAGE_LRU:
> >>> + case SCAN_PTE_NON_PRESENT:
> >>> + case SCAN_PTE_UFFD_WP:
> >>> + case SCAN_ALLOC_HUGE_PAGE_FAIL:
> >>> + goto next_order;
> >>> + /* Cases were no further collapse is possible */
> >>> + case SCAN_CGROUP_CHARGE_FAIL:
> >>> + case SCAN_COPY_MC:
> >>> + case SCAN_ADDRESS_RANGE:
> >>> + case SCAN_NO_PTE_TABLE:
> >>> + case SCAN_ANY_PROCESS:
> >>> + case SCAN_VMA_NULL:
> >>> + case SCAN_VMA_CHECK:
> >>> + case SCAN_SCAN_ABORT:
> >>> + case SCAN_PAGE_ANON:
> >>> + case SCAN_PMD_MAPPED:
> >>> + case SCAN_FAIL:
> >>> + default:
> >>
> >> Agree with david, let's spell them out please :)
> >
> > I believe David is arguing for the opposite. To drop all these spelt out cases
> > and just leave the default case.
> >
> > @david is that correct or did I misunderstand that.
>
> Either spell all out (no default) OR add a default.
>
> I prefer to just ... use the default :)
I mean yup that's fine too I guess, all or nothing, something in between is
weird!
>
> --
> Cheers,
>
> David
Cheers, Lorenzo
^ permalink raw reply
* Re: [Intel-wired-lan] [PATCH net-next v2 08/13] bnxt: use snapshot in bnxt_cfg_rx_mode
From: Stanislav Fomichev @ 2026-03-19 15:54 UTC (permalink / raw)
To: Loktionov, Aleksandr
Cc: Stanislav Fomichev, netdev@vger.kernel.org, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org,
andrew+netdev@lunn.ch, michael.chan@broadcom.com,
pavan.chebbi@broadcom.com, Nguyen, Anthony L, Kitszel, Przemyslaw,
saeedm@nvidia.com, tariqt@nvidia.com, mbloch@nvidia.com,
alexanderduyck@fb.com, kernel-team@meta.com,
johannes@sipsolutions.net, sd@queasysnail.net, jianbol@nvidia.com,
dtatulea@nvidia.com, mohsin.bashr@gmail.com, Keller, Jacob E,
willemb@google.com, skhawaja@google.com, bestswngs@gmail.com,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
leon@kernel.org
In-Reply-To: <IA3PR11MB89866985981DB64EFEBDF0ACE54FA@IA3PR11MB8986.namprd11.prod.outlook.com>
On 03/19, Loktionov, Aleksandr wrote:
>
>
> > -----Original Message-----
> > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> > Of Stanislav Fomichev
> > Sent: Wednesday, March 18, 2026 4:03 PM
> > To: netdev@vger.kernel.org
> > Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> > pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> > skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> > michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> > L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> > <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> > mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> > johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> > dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> > Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> > skhawaja@google.com; bestswngs@gmail.com; linux-doc@vger.kernel.org;
> > linux-kernel@vger.kernel.org; intel-wired-lan@lists.osuosl.org; linux-
> > rdma@vger.kernel.org; linux-wireless@vger.kernel.org; linux-
> > kselftest@vger.kernel.org; leon@kernel.org
> > Subject: [Intel-wired-lan] [PATCH net-next v2 08/13] bnxt: use
> > snapshot in bnxt_cfg_rx_mode
> >
> > With the introduction of ndo_set_rx_mode_async (as discussed in [0])
> > we can call bnxt_cfg_rx_mode directly. Convert bnxt_cfg_rx_mode to use
> > uc/mc snapshots and move its call in bnxt_sp_task to the section that
> > resets BNXT_STATE_IN_SP_TASK. Switch to direct call in
> > bnxt_set_rx_mode.
> >
> > 0:
> > https://lore.kernel.org/netdev/CACKFLi=5vj8hPqEUKDd8RTw3au5G+zRgQEqjF+
> > 6NZnyoNm90KA@mail.gmail.com/
> >
> > Cc: Michael Chan <michael.chan@broadcom.com>
> > Cc: Pavan Chebbi <pavan.chebbi@broadcom.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > ---
> > drivers/net/ethernet/broadcom/bnxt/bnxt.c | 24 ++++++++++++++--------
> > -
> > 1 file changed, 15 insertions(+), 9 deletions(-)
>
> ...
>
> > -static int bnxt_cfg_rx_mode(struct bnxt *bp)
> > +static int bnxt_cfg_rx_mode(struct bnxt *bp, struct
> > netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct net_device *dev = bp->dev;
> > struct bnxt_vnic_info *vnic = &bp-
> > >vnic_info[BNXT_VNIC_DEFAULT];
> > @@ -13623,7 +13625,7 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
> > bool uc_update;
> >
> > netif_addr_lock_bh(dev);
> > - uc_update = bnxt_uc_list_updated(bp, &dev->uc);
> > + uc_update = bnxt_uc_list_updated(bp, uc);
> > netif_addr_unlock_bh(dev);
> >
> > if (!uc_update)
> > @@ -13642,7 +13644,7 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
> > if (netdev_uc_count(dev) > (BNXT_MAX_UC_ADDRS - 1)) {
> > vnic->rx_mask |=
> > CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
> This limit check uses the live device list, dev->uc.
> In the new async model, the live list can differ from the snapshot.
Oh, yes, good catch! Will do s/netdev_uc_count/netdev_hw_addr_list_count(uc).
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox