On Wed, Oct 14, 2026 at 09:26:47PM -0300, Jason Gunthorpe wrote: > If we silently truncate that to the range of the bitmap, like this > does, then we also are silently lossing dirty marks. The userspace > will call again with an iova range stepped ahead and instead of seeing > the early blocks being dirty they will be marked as clean.
Right, the clip turns an overrun into silent dirty loss; failing the call is better. I also saw your reply to Samarth's record_dirty() patch [1]: with both changes, a dirty entry that is not wholly inside the bitmap fails the call. Samarth offered to send a v2 of both patches; I'm happy to leave 1/4 to whichever of you prefers and rebase my tests on top. A few things I'd like to check before I rework the rest: 1) The dirty bit is still cleared when the record fails. In the record_dirty() you proposed, as in visit_dirty() in io-pgtable-arm, the entry is made clean unless IOMMU_DIRTY_NO_CLEAR, whatever iova_bitmap_set() did. With start_va rounded down to the entry, a query that starts or ends inside a dirty huge IOPTE now fails this way too, and a retry with an aligned range sees the entry clean. Is -EPROTO meant to be fatal for userspace (e.g. abort the migration), or should the clear be skipped once bitmap->err is set? 2) Could you point me at the patch that adds bitmap->err? On mainline iommu_read_and_clear_dirty() ignores the return of iova_bitmap_for_each() and returns 0, so I assume that patch also changes this. Does it cover the VFIO DMA logging path as well (vfio_device_log_read_and_clear(), with mlx5 and pds calling iova_bitmap_set())? 3) Patch 2 tests the clip, so with your change it fails: the 1M IOPTE at MOCK_APERTURE_START is rejected whole against the 128K query, and bitmap[0] stays clear. I can respin it to expect EPROTO, keep the guard check past the bitmap, and add a query that starts inside the IOPTE, on top of the bitmap->err patch. Patches 3 and 4 still apply, I think: iova = 0 with length = 0 passes iommufd_check_iova_range(), and __iommu_read_and_clear_dirty() then walks [0, ULONG_MAX]. With your check nothing gets recorded, but the dirty bits it walks over are still cleared. [1] https://lore.kernel.org/all/[email protected]/ Thanks, Andrea

