On 10/13/26 17:04, Lorenzo Stoakes (ARM) wrote: > Describe the newly introduced discontiguous kernel page mapping mechanism, > detailing how to use it sensibly and how the API looks. > > Explicitly detail the various discontiguous actions available and how to > use them. > > Reviewed-by: Suren Baghdasaryan <[email protected]> > Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]> > --- > Documentation/filesystems/mmap_prepare.rst | 81 > ++++++++++++++++++++++++++++++ > 1 file changed, 81 insertions(+) > > diff --git a/Documentation/filesystems/mmap_prepare.rst > b/Documentation/filesystems/mmap_prepare.rst > index 82c99c95ad85..b5afbb33e5c8 100644 > --- a/Documentation/filesystems/mmap_prepare.rst > +++ b/Documentation/filesystems/mmap_prepare.rst > @@ -164,5 +164,86 @@ pointer. These are: > sufficient entries in the page array to cover the entire range of the > described VMA. > > +* mmap_action_map_discontig_kernel_pages() - Maps a discontiguous range of > + `struct page` pointers over the VMA. They must span from the start of the > VMA, > + but may terminate prior to the end (leaving the remainder unmapped). > + > **NOTE:** The ``action`` field should never normally be manipulated directly, > rather you ought to use one of these helpers. > + > +Discontiguous Actions > +===================== > + > +Some actions can be performed across discontiguous ranges. > + > +Map kernel pages > +---------------- > + > +To map kernel pages discontiguously, you must provide hooks using ``struct > +discontig_kernel_page_ops``: > + > +.. code-block:: C > + > + struct discontig_kernel_page_ops { > + int (*init)(void *vm_private_data, void **private); > + int (*get)(struct discontig_kernel_page_state *state); > + }; > + > +The ``init`` hook is optional and allows state to be established before the > +operation starts, for instance taking a reference count. Nothing is invoked > +after the operation, so ``init`` must not leave locks held, and state that > must > +be released once the mapping goes away should be released in > +``vm_ops->close``. > + > +The ``init`` hook, if provided, is invoked prior to the operation starting. > It > +may update what is pointed to by ``vm_private_data`` and/or ``private``. If > an > +error is returned, then the operation is aborted. The ``private`` field can > be > +reassigned. > + > +**NOTE:** The operation may sleep between invocations of ``get``, so locks > +needed to stabilise state must be taken and released within each hook. > + > +The ``get`` handler is the key means through which the operation is > +executed. The current state of the operation is provided through ``struct > +discontig_kernel_page_state``: > + > +.. code-block:: C > + > + struct discontig_kernel_page_state { > + /* Map state. */ > + unsigned long start; /* Start address of VMA. */ > + unsigned long end; /* End address of VMA. */ > + unsigned long addr; /* The current address to be mapped. > */ > + pgoff_t pgoff; /* The current pgoff to be mapped. */ > + unsigned long nr_pages_mapped; /* The number of pages mapped. */ > + unsigned long nr_pages_remain; /* The number of pages remaining. */ > + > + /* User-defined state. */ > + void *vm_private_data; /* VMA private data. */ > + void *private; /* Mapping private data. */ > + > + /* Users should not touch these, use discontig_kernel_map_*() > helpers. */ > + ... internal fields ... > + }; > + > +With ``private`` being an additional user-controllable state variable, > +initialised via ``mmap_action_map_discontig_kernel_pages()``, and > +``vm_private_data`` being equal to the ``desc->private_data`` field set in > +the ``mmap_prepare()`` hook. > + > +In the ``get`` hook, the user must choose how to map kernel pages: > + > +* ``discontig_kernel_map_abort()`` - Call this to abort the operation, > whatever > + has been mapped so far will be retained, the rest of the mapping will > SIGBUS > + if accessed. > +* ``discontig_kernel_map_page()`` - Maps a single page, correctly handling
"single page" can be misleading with compound pages. "Map an entire (compound) page" or sth like that would be clearer. Acked-by: David Hildenbrand (Arm) <[email protected]> -- Cheers, David
