Hi Lorenzo, On Mon, Aug 11, 2025 at 03:59:38PM +0100, Lorenzo Stoakes wrote: > Document the new behaviour introduced in Linux 6.17 whereby it is now > possible to move multiple mappings in a single operation, as long as the > operation is purely a move, that is old_size is equal to new_size and > MREMAP_FIXED is specified. > > This change also explains the limitations of of this method and the > possibility of partial failure. > > Finally, we pluralise language where it makes sense to so the documentation > does not contradict either this new capability nor the pre-existing edge > case. > > Example code is enclosed below demonstrating the behaviour which is now > possible: > > int main(void) > { > unsigned long page_size = sysconf(_SC_PAGESIZE); > void *ptr = mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE, > MAP_ANON | MAP_PRIVATE, -1, 0); > void *tgt_ptr = mmap(NULL, 10 * page_size, PROT_NONE, > MAP_ANON | MAP_PRIVATE, -1, 0); > int i; > > if (ptr == MAP_FAILED || tgt_ptr == MAP_FAILED) { > perror("mmap"); > return EXIT_FAILURE; > } > > /* Unmap every other page. */ > for (i = 1; i < 10; i += 2) > munmap(ptr + i * page_size, page_size); > > /* Now move all 5 distinct mappings to tgt_ptr. */ > ptr = mremap(ptr, 10 * page_size, 10 * page_size, > MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr); > if (ptr == MAP_FAILED) { > perror("mremap"); > return EXIT_FAILURE; > } > > return EXIT_SUCCESS; > } I've applied some editorial changes to the program. > > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx> Thanks! I've applied the patch, with a small amendment (see below). <https://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git/commit/?h=contrib&id=d99a3495372a69b48309f2a1a4e2067af2bfbe69> Have a lovely day! Alex > --- > man/man2/mremap.2 | 68 +++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 57 insertions(+), 11 deletions(-) > > diff --git a/man/man2/mremap.2 b/man/man2/mremap.2 > index 4e3c8e54e..6d14bf627 100644 > --- a/man/man2/mremap.2 > +++ b/man/man2/mremap.2 > @@ -35,22 +35,36 @@ and using the > .B MREMAP_FIXED > flag > (see below). > +Since Linux 6.17, > +while > +.I old_address > +must be mapped, > +.I old_size > +may span multiple mappings > +including unmapped areas between > +them when performing a move like this. And I've reworded this last line. Repetitive consistent language helps understanding documentation, so it's better to repeat "a simple move" here again. diff --git i/man/man2/mremap.2 w/man/man2/mremap.2 index 6d14bf627..65b4d5f58 100644 --- i/man/man2/mremap.2 +++ w/man/man2/mremap.2 @@ -42,7 +42,7 @@ .SH DESCRIPTION .I old_size may span multiple mappings including unmapped areas between -them when performing a move like this. +them when performing a simple move. The .B MREMAP_DONTUNMAP flag may also be specified. > The > .B MREMAP_DONTUNMAP > flag may also be specified. > .P > +If the operation is not > +simply moving mappings, > +then > +.I old_size > +must span only a single mapping. > +.P > .I old_address > -is the old address of the virtual memory block that you > -want to expand (or shrink). > +is the old address of the first virtual memory block that you > +want to expand, shrink, and/or move. > Note that > .I old_address > has to be page aligned. > .I old_size > -is the old size of the > -virtual memory block. > +is the size of the range containing > +virtual memory blocks to be manipulated. > .I new_size > is the requested size of the > -virtual memory block after the resize. > +virtual memory blocks after the resize. > An optional fifth argument, > .IR new_address , > may be provided; see the description of > @@ -119,13 +133,42 @@ If > is specified, then > .B MREMAP_MAYMOVE > must also be specified. > +.IP > +Since Linux 6.17, > +if > +.I old_size > +is equal to > +.I new_size > +and > +.B MREMAP_FIXED > +is specified, then > +.I old_size > +may span beyond the mapping in which > +.I old_address > +resides. > +In this case, > +gaps between mappings in the original range > +are maintained in the new range. > +The whole operation is performed atomically > +unless an error arises, > +in which case the operation may be partially > +completed, > +that is, > +some mappings may be moved and others not. > +.IP > +Moving multiple mappings is not permitted if > +any of those mappings have either > +been registered with > +.BR userfaultfd (2) , > +or map drivers that > +specify their own custom address mapping logic. > .TP > .BR MREMAP_DONTUNMAP " (since Linux 5.7)" > .\" commit e346b3813067d4b17383f975f197a9aa28a3b077 > This flag, which must be used in conjunction with > .BR MREMAP_MAYMOVE , > -remaps a mapping to a new address but does not unmap the mapping at > -.IR old_address . > +remaps mappings to a new address but does not unmap them > +from their original address. > .IP > The > .B MREMAP_DONTUNMAP > @@ -163,13 +206,13 @@ mapped. > See NOTES for some possible applications of > .BR MREMAP_DONTUNMAP . > .P > -If the memory segment specified by > +If the memory segments specified by > .I old_address > and > .I old_size > -is locked (using > +are locked (using > .BR mlock (2) > -or similar), then this lock is maintained when the segment is > +or similar), then this lock is maintained when the segments are > resized and/or relocated. > As a consequence, the amount of memory locked by the process may change. > .SH RETURN VALUE > @@ -202,7 +245,10 @@ virtual memory address for this process. > You can also get > .B EFAULT > even if there exist mappings that cover the > -whole address space requested, but those mappings are of different types. > +whole address space requested, but those mappings are of different types, > +and the > +.BR mremap () > +operation being performed does not support this. > .TP > .B EINVAL > An invalid argument was given. > -- > 2.50.1 > -- <https://www.alejandro-colomar.es/>
Attachment:
signature.asc
Description: PGP signature