* [PATCH 0/2] iommufd: remove the last use of set_page_dirty_lock()
@ 2026-10-31 20:33 Tal Zussman
2026-10-31 20:33 ` [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec Tal Zussman
2026-10-31 20:33 ` [PATCH 2/2] iommufd: copy to and from folios in batch_rw() Tal Zussman
0 siblings, 2 replies; 8+ messages in thread
From: Tal Zussman @ 2026-10-31 20:33 UTC (permalink / raw)
To: Jason Gunthorpe, Kevin Tian, Joerg Roedel (AMD),
Will Deacon, Robin Murphy, Greg Kroah-Hartman,
Jean-Philippe Brucker
Cc: iommu, linux-kernel, Tal Zussman
batch_rw() copies to and from pinned user pages one page at a time and
dirties each with set_page_dirty_lock(). The second patch walks the pfn
batch a folio at a time with memcpy_to_folio() and memcpy_from_folio()
and marks each folio dirty once. It removes the last use of
set_page_dirty_lock() in iommufd.
The issue fixed in the first patch was found while testing the second:
iommufd_fail_nth turned up a dev_iommu leak in iommu_fwspec_init() under
kmemleak. The fix is independent and could go through the iommu tree on
its own.
Tested on x86 under virtme-ng with KASAN and lockdep against the iommufd
mock driver. The selftests and iommufd_fail_nth all pass.
With ftrace timing iopt_pages_rw_slow() through the mock driver on a
non-debug kernel, slow-path writes to THP-backed pages drop from ~1310 to
~930 ns/page (now the same cost as a read), and writes to 4K folios drop
~9%.
---
Tal Zussman (2):
iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec
iommufd: copy to and from folios in batch_rw()
drivers/iommu/iommu.c | 6 +++++-
drivers/iommu/iommufd/pages.c | 35 ++++++++++++++++++++---------------
2 files changed, 25 insertions(+), 16 deletions(-)
---
base-commit: 04bcf84613346b973a8cc0c59238b6b5bc902688
change-id: 20261015-iommufd-folio-dirty-8abff4281f3a
Best regards,
--
Tal Zussman <tz2294@columbia.edu>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec 2026-10-31 20:33 [PATCH 0/2] iommufd: remove the last use of set_page_dirty_lock() Tal Zussman @ 2026-10-31 20:33 ` Tal Zussman 2026-11-02 16:51 ` Robin Murphy 2026-10-31 20:33 ` [PATCH 2/2] iommufd: copy to and from folios in batch_rw() Tal Zussman 1 sibling, 1 reply; 8+ messages in thread From: Tal Zussman @ 2026-10-31 20:33 UTC (permalink / raw) To: Jason Gunthorpe, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Robin Murphy, Greg Kroah-Hartman, Jean-Philippe Brucker Cc: iommu, linux-kernel, Tal Zussman iommu_fwspec_init() allocates dev->iommu with dev_iommu_get() and then the fwspec. If the fwspec allocation fails it returns -ENOMEM but leaves dev->iommu allocated, and it leaks. kmemleak reports it when iommufd_fail_nth injects the allocation failure: unreferenced object 0xffff88811c138b00 (size 192): comm "iommufd_fail_nt", pid 783 backtrace: __kmalloc_cache_noprof dev_iommu_get iommu_fwspec_init iommu_mock_device_add iommufd_test iommufd_fops_ioctl Free dev->iommu on failure if this call allocated it. iommu_init_device() allocates it before calling into the driver and frees it on its own error path, so leave it alone in that case. Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") Signed-off-by: Tal Zussman <tz2294@columbia.edu> --- drivers/iommu/iommu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index cd1bca7ede9a..69be8819e05d 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -3074,6 +3074,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) { const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + bool new_iommu = !dev->iommu; if (!iommu) return driver_deferred_probe_check_state(dev); @@ -3088,8 +3089,11 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) /* Preallocate for the overwhelmingly common case of 1 ID */ fwspec = kzalloc_flex(*fwspec, ids, 1); - if (!fwspec) + if (!fwspec) { + if (new_iommu) + dev_iommu_free(dev); return -ENOMEM; + } fwnode_handle_get(iommu_fwnode); fwspec->iommu_fwnode = iommu_fwnode; -- 2.39.5 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec 2026-10-31 20:33 ` [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec Tal Zussman @ 2026-11-02 16:51 ` Robin Murphy 2026-11-03 12:30 ` Tal Zussman 2026-11-03 19:32 ` Jason Gunthorpe 0 siblings, 2 replies; 8+ messages in thread From: Robin Murphy @ 2026-11-02 16:51 UTC (permalink / raw) To: Tal Zussman, Jason Gunthorpe, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Greg Kroah-Hartman, Jean-Philippe Brucker Cc: iommu, linux-kernel On 31/10/2026 8:33 pm, Tal Zussman wrote: > iommu_fwspec_init() allocates dev->iommu with dev_iommu_get() and then > the fwspec. If the fwspec allocation fails it returns -ENOMEM but leaves > dev->iommu allocated, and it leaks. > > kmemleak reports it when iommufd_fail_nth injects the allocation > failure: > > unreferenced object 0xffff88811c138b00 (size 192): > comm "iommufd_fail_nt", pid 783 > backtrace: > __kmalloc_cache_noprof > dev_iommu_get > iommu_fwspec_init > iommu_mock_device_add > iommufd_test > iommufd_fops_ioctl > > Free dev->iommu on failure if this call allocated it. iommu_init_device() > allocates it before calling into the driver and frees it on its own > error path, so leave it alone in that case. > > Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") No, the bug is clearly the early return in 2a918911ed3d ("iommufd: Register iommufd mock devices with fwspec"), so fix it there please. iommu_fwspec_init() has always been designed to be called in conjunction with iommu_probe_device() which handles cleanup appropriately. All of this mock_device hackery not using the proper probe paths is enough of a pain as it is... Thanks, Robin. > Signed-off-by: Tal Zussman <tz2294@columbia.edu> > --- > drivers/iommu/iommu.c | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index cd1bca7ede9a..69be8819e05d 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -3074,6 +3074,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) > { > const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); > struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); > + bool new_iommu = !dev->iommu; > > if (!iommu) > return driver_deferred_probe_check_state(dev); > @@ -3088,8 +3089,11 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) > > /* Preallocate for the overwhelmingly common case of 1 ID */ > fwspec = kzalloc_flex(*fwspec, ids, 1); > - if (!fwspec) > + if (!fwspec) { > + if (new_iommu) > + dev_iommu_free(dev); > return -ENOMEM; > + } > > fwnode_handle_get(iommu_fwnode); > fwspec->iommu_fwnode = iommu_fwnode; > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec 2026-11-02 16:51 ` Robin Murphy @ 2026-11-03 12:30 ` Tal Zussman 2026-11-03 19:32 ` Jason Gunthorpe 1 sibling, 0 replies; 8+ messages in thread From: Tal Zussman @ 2026-11-03 12:30 UTC (permalink / raw) To: Robin Murphy, Jason Gunthorpe, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Greg Kroah-Hartman, Jean-Philippe Brucker Cc: iommu, linux-kernel On 11/2/26 11:51 AM, Robin Murphy wrote: > On 31/10/2026 8:33 pm, Tal Zussman wrote: >> iommu_fwspec_init() allocates dev->iommu with dev_iommu_get() and then >> the fwspec. If the fwspec allocation fails it returns -ENOMEM but leaves >> dev->iommu allocated, and it leaks. >> >> kmemleak reports it when iommufd_fail_nth injects the allocation >> failure: >> >> unreferenced object 0xffff88811c138b00 (size 192): >> comm "iommufd_fail_nt", pid 783 >> backtrace: >> __kmalloc_cache_noprof >> dev_iommu_get >> iommu_fwspec_init >> iommu_mock_device_add >> iommufd_test >> iommufd_fops_ioctl >> >> Free dev->iommu on failure if this call allocated it. iommu_init_device() >> allocates it before calling into the driver and frees it on its own >> error path, so leave it alone in that case. >> >> Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") > > No, the bug is clearly the early return in 2a918911ed3d ("iommufd: > Register iommufd mock devices with fwspec"), so fix it there please. > iommu_fwspec_init() has always been designed to be called in conjunction > with iommu_probe_device() which handles cleanup appropriately. All of > this mock_device hackery not using the proper probe paths is enough of a > pain as it is... > > Thanks, > Robin. > Thanks for the review! I'll change this for v2. - Tal >> Signed-off-by: Tal Zussman <tz2294@columbia.edu> >> --- >> drivers/iommu/iommu.c | 6 +++++- >> 1 file changed, 5 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c >> index cd1bca7ede9a..69be8819e05d 100644 >> --- a/drivers/iommu/iommu.c >> +++ b/drivers/iommu/iommu.c >> @@ -3074,6 +3074,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) >> { >> const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); >> struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); >> + bool new_iommu = !dev->iommu; >> >> if (!iommu) >> return driver_deferred_probe_check_state(dev); >> @@ -3088,8 +3089,11 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) >> >> /* Preallocate for the overwhelmingly common case of 1 ID */ >> fwspec = kzalloc_flex(*fwspec, ids, 1); >> - if (!fwspec) >> + if (!fwspec) { >> + if (new_iommu) >> + dev_iommu_free(dev); >> return -ENOMEM; >> + } >> >> fwnode_handle_get(iommu_fwnode); >> fwspec->iommu_fwnode = iommu_fwnode; >> > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec 2026-11-02 16:51 ` Robin Murphy 2026-11-03 12:30 ` Tal Zussman @ 2026-11-03 19:32 ` Jason Gunthorpe 2026-11-03 20:18 ` Robin Murphy 1 sibling, 1 reply; 8+ messages in thread From: Jason Gunthorpe @ 2026-11-03 19:32 UTC (permalink / raw) To: Robin Murphy Cc: Tal Zussman, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Greg Kroah-Hartman, Jean-Philippe Brucker, iommu, linux-kernel On Mon, Nov 02, 2026 at 04:51:05PM +0000, Robin Murphy wrote: > On 31/10/2026 8:33 pm, Tal Zussman wrote: > > iommu_fwspec_init() allocates dev->iommu with dev_iommu_get() and then > > the fwspec. If the fwspec allocation fails it returns -ENOMEM but leaves > > dev->iommu allocated, and it leaks. > > > > kmemleak reports it when iommufd_fail_nth injects the allocation > > failure: > > > > unreferenced object 0xffff88811c138b00 (size 192): > > comm "iommufd_fail_nt", pid 783 > > backtrace: > > __kmalloc_cache_noprof > > dev_iommu_get > > iommu_fwspec_init > > iommu_mock_device_add > > iommufd_test > > iommufd_fops_ioctl > > > > Free dev->iommu on failure if this call allocated it. iommu_init_device() > > allocates it before calling into the driver and frees it on its own > > error path, so leave it alone in that case. > > > > Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") > > No, the bug is clearly the early return in 2a918911ed3d ("iommufd: Register > iommufd mock devices with fwspec"), so fix it there please. > iommu_fwspec_init() has always been designed to be called in conjunction > with iommu_probe_device() which handles cleanup appropriately. Asking AI to audit this found the other case I remember... Yes: ACPI DMA configuration during driver binding can leave dev->iommu allocated after failure: really_probe() -> dev->bus->dma_configure() -> acpi_dma_configure_id() -> acpi_iommu_configure_id() -> IORT / RIMT / VIOT -> acpi_iommu_fwspec_init() -> iommu_fwspec_init() If dev_iommu_get() allocates successfully and the subsequent fwspec allocation fails, acpi_iommu_configure_id() (line 1614) does no cleanup. acpi_dma_configure_id() (line 1670) ignores errors other than -EPROBE_DEFER. This invocation has no enclosing iommu_init_device() to unwind it. The OF path has its own manual free fix already, it doesn't rely on iommu_probe_device() to clean it. The other driver users are the only things actually protected by ops->probe_device(). > > @@ -3074,6 +3074,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) > > { > > const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); > > struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); > > + bool new_iommu = !dev->iommu; > > if (!iommu) > > return driver_deferred_probe_check_state(dev); > > @@ -3088,8 +3089,11 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) > > /* Preallocate for the overwhelmingly common case of 1 ID */ > > fwspec = kzalloc_flex(*fwspec, ids, 1); > > - if (!fwspec) > > + if (!fwspec) { > > + if (new_iommu) > > + dev_iommu_free(dev); > > return -ENOMEM; > > + } Just move this allocation before the dev_iommu_get() and free it if the get fails. Then the function has a more sensible calling convention that error means it doesn't need any unwinding. The new_iommu is a little too weird. Jason ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec 2026-11-03 19:32 ` Jason Gunthorpe @ 2026-11-03 20:18 ` Robin Murphy 0 siblings, 0 replies; 8+ messages in thread From: Robin Murphy @ 2026-11-03 20:18 UTC (permalink / raw) To: Jason Gunthorpe Cc: Tal Zussman, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Greg Kroah-Hartman, Jean-Philippe Brucker, iommu, linux-kernel On 2026-11-03 7:32 pm, Jason Gunthorpe wrote: > On Mon, Nov 02, 2026 at 04:51:05PM +0000, Robin Murphy wrote: >> On 31/10/2026 8:33 pm, Tal Zussman wrote: >>> iommu_fwspec_init() allocates dev->iommu with dev_iommu_get() and then >>> the fwspec. If the fwspec allocation fails it returns -ENOMEM but leaves >>> dev->iommu allocated, and it leaks. >>> >>> kmemleak reports it when iommufd_fail_nth injects the allocation >>> failure: >>> >>> unreferenced object 0xffff88811c138b00 (size 192): >>> comm "iommufd_fail_nt", pid 783 >>> backtrace: >>> __kmalloc_cache_noprof >>> dev_iommu_get >>> iommu_fwspec_init >>> iommu_mock_device_add >>> iommufd_test >>> iommufd_fops_ioctl >>> >>> Free dev->iommu on failure if this call allocated it. iommu_init_device() >>> allocates it before calling into the driver and frees it on its own >>> error path, so leave it alone in that case. >>> >>> Fixes: 72acd9df18f1 ("iommu: Move iommu_fwspec to struct dev_iommu") >> >> No, the bug is clearly the early return in 2a918911ed3d ("iommufd: Register >> iommufd mock devices with fwspec"), so fix it there please. >> iommu_fwspec_init() has always been designed to be called in conjunction >> with iommu_probe_device() which handles cleanup appropriately. > > Asking AI to audit this found the other case I remember... > > Yes: ACPI DMA configuration during driver binding can leave dev->iommu > allocated after failure: > > really_probe() > -> dev->bus->dma_configure() > -> acpi_dma_configure_id() > -> acpi_iommu_configure_id() > -> IORT / RIMT / VIOT > -> acpi_iommu_fwspec_init() > -> iommu_fwspec_init() > > If dev_iommu_get() allocates successfully and the subsequent fwspec > allocation fails, acpi_iommu_configure_id() (line 1614) does no > cleanup. acpi_dma_configure_id() (line 1670) ignores errors other than > -EPROBE_DEFER. This invocation has no enclosing iommu_init_device() to > unwind it. Yes, because that path will no longer allocate - if we reach iommu_fwspec_init() from the really_probe path at all now it's because the IOMMU is not yet registered, thus we'll always take the early return. In fact I think the only reason to still have dev_iommu_get() in iommu_fwspec_init(), rather than just dereferencing dev->iommu directly, is for the sake of those few remaining drivers which abuse of_dma_configure() directly that I'm not sure what to do about. Thanks, Robin. > The OF path has its own manual free fix already, it doesn't rely on > iommu_probe_device() to clean it. The other driver users are the only > things actually protected by ops->probe_device(). > >>> @@ -3074,6 +3074,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) >>> { >>> const struct iommu_device *iommu = iommu_from_fwnode(iommu_fwnode); >>> struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); >>> + bool new_iommu = !dev->iommu; >>> if (!iommu) >>> return driver_deferred_probe_check_state(dev); >>> @@ -3088,8 +3089,11 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) >>> /* Preallocate for the overwhelmingly common case of 1 ID */ >>> fwspec = kzalloc_flex(*fwspec, ids, 1); >>> - if (!fwspec) >>> + if (!fwspec) { >>> + if (new_iommu) >>> + dev_iommu_free(dev); >>> return -ENOMEM; >>> + } > > Just move this allocation before the dev_iommu_get() and free it if > the get fails. Then the function has a more sensible calling > convention that error means it doesn't need any unwinding. The > new_iommu is a little too weird. > > Jason ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] iommufd: copy to and from folios in batch_rw() 2026-10-31 20:33 [PATCH 0/2] iommufd: remove the last use of set_page_dirty_lock() Tal Zussman 2026-10-31 20:33 ` [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec Tal Zussman @ 2026-10-31 20:33 ` Tal Zussman 2026-11-03 19:36 ` Jason Gunthorpe 1 sibling, 1 reply; 8+ messages in thread From: Tal Zussman @ 2026-10-31 20:33 UTC (permalink / raw) To: Jason Gunthorpe, Kevin Tian, Joerg Roedel (AMD), Will Deacon, Robin Murphy, Greg Kroah-Hartman, Jean-Philippe Brucker Cc: iommu, linux-kernel, Tal Zussman batch_rw() copies one page at a time and, for writes, dirties each page with set_page_dirty_lock(). Walk the pfn batch a folio at a time instead, copying with memcpy_to_folio() and memcpy_from_folio() and marking each folio dirty once. Convert the single-page copy in iopt_pages_rw_page() to the same helper. iopt_pages_rw_access() rejects dmabuf pages, so only pinned user memory and memfd pages can reach batch_rw(), and those are always folios. memcpy_to_folio() also flushes the dcache after the write, which the open-coded memcpy() didn't. This removes the last use of set_page_dirty_lock() in iommufd. With ftrace timing iopt_pages_rw_slow() through the mock driver on a non-debug kernel, slow-path writes to THP-backed pages drop from ~1310 to ~930 ns/page (now the same cost as a read), and writes to 4K folios drop ~9%. Signed-off-by: Tal Zussman <tz2294@columbia.edu> --- drivers/iommu/iommufd/pages.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c index 2f6153108add..133fed4495dd 100644 --- a/drivers/iommu/iommufd/pages.c +++ b/drivers/iommu/iommufd/pages.c @@ -721,19 +721,15 @@ static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages, } } -static void copy_data_page(struct page *page, void *data, unsigned long offset, - size_t length, unsigned int flags) +static void copy_data_folio(struct folio *folio, size_t offset, void *data, + size_t length, unsigned int flags) { - void *mem; - - mem = kmap_local_page(page); if (flags & IOMMUFD_ACCESS_RW_WRITE) { - memcpy(mem + offset, data, length); - set_page_dirty_lock(page); + memcpy_to_folio(folio, offset, data, length); + folio_mark_dirty_lock(folio); } else { - memcpy(data, mem + offset, length); + memcpy_from_folio(data, folio, offset, length); } - kunmap_local(mem); } static unsigned long batch_rw(struct pfn_batch *batch, void *data, @@ -745,15 +741,21 @@ static unsigned long batch_rw(struct pfn_batch *batch, void *data, unsigned int cur = 0; while (cur < batch->end) { - unsigned long bytes = min(length, PAGE_SIZE - offset); - - copy_data_page(pfn_to_page(batch->pfns[cur] + npage), data, - offset, bytes, flags); + unsigned long pfn = batch->pfns[cur] + npage; + struct folio *folio = pfn_folio(pfn); + unsigned long idx = pfn - folio_pfn(folio); + unsigned long nr = min_t(unsigned long, + folio_nr_pages(folio) - idx, + batch->npfns[cur] - npage); + unsigned long bytes = min(length, nr * PAGE_SIZE - offset); + + copy_data_folio(folio, idx * PAGE_SIZE + offset, data, bytes, + flags); offset = 0; length -= bytes; data += bytes; copied += bytes; - npage++; + npage += nr; if (npage == batch->npfns[cur]) { npage = 0; cur++; @@ -2306,6 +2308,7 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index, unsigned long length, unsigned int flags) { struct page *page = NULL; + struct folio *folio; int rc; if (IS_ENABLED(CONFIG_IOMMUFD_TEST) && @@ -2332,7 +2335,9 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index, rc = -EINVAL; goto out_mmput; } - copy_data_page(page, data, offset, length, flags); + folio = page_folio(page); + copy_data_folio(folio, folio_page_idx(folio, page) * PAGE_SIZE + offset, + data, length, flags); unpin_user_page(page); rc = 0; -- 2.39.5 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] iommufd: copy to and from folios in batch_rw() 2026-10-31 20:33 ` [PATCH 2/2] iommufd: copy to and from folios in batch_rw() Tal Zussman @ 2026-11-03 19:36 ` Jason Gunthorpe 0 siblings, 0 replies; 8+ messages in thread From: Jason Gunthorpe @ 2026-11-03 19:36 UTC (permalink / raw) To: Tal Zussman Cc: Kevin Tian, Joerg Roedel (AMD), Will Deacon, Robin Murphy, Greg Kroah-Hartman, Jean-Philippe Brucker, iommu, linux-kernel On Sat, Oct 31, 2026 at 04:33:19PM -0400, Tal Zussman wrote: > batch_rw() copies one page at a time and, for writes, dirties each page > with set_page_dirty_lock(). Walk the pfn batch a folio at a time > instead, copying with memcpy_to_folio() and memcpy_from_folio() and > marking each folio dirty once. Convert the single-page copy in > iopt_pages_rw_page() to the same helper. > > iopt_pages_rw_access() rejects dmabuf pages, so only pinned user memory > and memfd pages can reach batch_rw(), and those are always folios. > > memcpy_to_folio() also flushes the dcache after the write, which the > open-coded memcpy() didn't. > > This removes the last use of set_page_dirty_lock() in iommufd. > > With ftrace timing iopt_pages_rw_slow() through the mock driver on a > non-debug kernel, slow-path writes to THP-backed pages drop from ~1310 to > ~930 ns/page (now the same cost as a read), and writes to 4K folios drop > ~9%. > > Signed-off-by: Tal Zussman <tz2294@columbia.edu> > --- > drivers/iommu/iommufd/pages.c | 35 ++++++++++++++++++++--------------- > 1 file changed, 20 insertions(+), 15 deletions(-) This looks reasonable to me Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Jason ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-03 20:18 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-31 20:33 [PATCH 0/2] iommufd: remove the last use of set_page_dirty_lock() Tal Zussman 2026-10-31 20:33 ` [PATCH 1/2] iommu: free dev->iommu when iommu_fwspec_init() cannot allocate the fwspec Tal Zussman 2026-11-02 16:51 ` Robin Murphy 2026-11-03 12:30 ` Tal Zussman 2026-11-03 19:32 ` Jason Gunthorpe 2026-11-03 20:18 ` Robin Murphy 2026-10-31 20:33 ` [PATCH 2/2] iommufd: copy to and from folios in batch_rw() Tal Zussman 2026-11-03 19:36 ` Jason Gunthorpe
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®