On Wed, Nov 27, 2024 at 10:36 PM Kent Overstreet <[email protected]> wrote: > When invoked from aio, mm_struct is guaranteed to outlive the request > since its lifetime is tied to the io_context - but that's not the case > for io_uring, it's possible that a process could be killed and mm_struct > goes away while a request is in flight. > > So if we're submitting the rest of the io asynchronously, we may need a > ref on mm_struct. > > Per Jens, this is not actually a bug because we're not yet flipping on > FMODE_NOWAIT, meaning io_uring will do the submission from an io_worker > kthread - but this patch is necessary for safely flipping on > FMODE_NOWAIT for more efficient submissions in the future.
Ah, one thing to look out for is that mm_struct has two types of refcounting, this patch mixes them up - I don't think my explanation of that was very clear: - mmgrab()/mmdrop() prevent the mm_struct itself being freed, but don't properly keep the mappings in it alive - mmget()/mmput() fully keep the MM alive An mmget() reference automatically also holds an mmgrab() reference, basically. For kthread_use_mm(), you need an mmget() reference; so the most straightforward option would be to mmget() when creating the asynchronous work and mmput() when you're done. But that has the disadvantage that the reference keeps the entire mm_struct with all the mappings inside it alive, and it even indirectly holds a reference to all the files mapped in the MM; though I don't know if that's really a problem here. If you want to avoid keeping the MM of an exiting process alive while the I/O is running, the neater pattern is to use mmgrab()/mmdrop() for your long-term reference, and then use mmget_not_zero()/mmput() around kthread_use_mm()/kthread_unuse_mm() (and bail if mmget_not_zero() fails). You can see this pattern in places like vfio_iommu_type1_dma_rw_chunk().
