On Sat, Aug 09, 2025 at 04:25:18PM +0200, Alejandro Colomar wrote: > Hi Lorenzo, > > On Tue, Aug 05, 2025 at 06:31:55PM +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. > > > > To make things clearer, also describe this 'pure move' operation, before > > expanding upon it to describe the newly introduced behaviour. > > Can we split this further into two commits? OK can do. > > > > > 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; > > } > > > > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx> > > --- > > man/man2/mremap.2 | 84 ++++++++++++++++++++++++++++++++++++++++------- > > 1 file changed, 73 insertions(+), 11 deletions(-) > > > > diff --git a/man/man2/mremap.2 b/man/man2/mremap.2 > > index 2168ca728..6ba51310c 100644 > > --- a/man/man2/mremap.2 > > +++ b/man/man2/mremap.2 > > @@ -25,18 +25,47 @@ moving it at the same time (controlled by the > > argument and > > the available virtual address space). > > .P > > +Mappings can also simply be moved > > +(without any resizing) > > +by specifying equal > > +.I old_size > > +and > > +.I new_size > > +and using the > > +.B MREMAP_FIXED > > +flag > > +(see below). > > +Since Linux 6.17, > > +while > > +.I old_address > > +must reside within a mapping, > > I don't understand this. What does it mean that old_address must reside > within a mapping? It's a point, not a size, so I'm not sure I > understand it. I think if it were a size it would be more confusing no? It's an address, the address must be located within an existing memory mapping. Will replace with 'located' for clarity. > > > +.I old_size > > +may span multiple mappings > > +which do not have to be > > +adjacent to one another when > > +performing a move like this. > > +The > > +.B MREMAP_DONTUNMAP > > +flag may 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 > > @@ -105,13 +134,43 @@ 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 > > + > > Why this blank? Oops that was a mistake, will fix on respin. > > > Cheers, > Alex > > > +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 > > @@ -149,13 +208,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 > > @@ -188,7 +247,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/>