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().

Reply via email to