[v4] Update mmap() flags and errors lists

DJ Delorie dj@redhat.com
Tue Jun 18 20:57:17 GMT 2024


Mathieu Desnoyers <mathieu.desnoyers@efficios.com> writes:
> I will review this patch based on my understanding of the Linux mmap(2)
> manual from Linux man-pages 6.03 2023-02-05. It is very much possible
> that your intent is not to match that specific syscall man page, in
> which case feel free to dismiss my concerns.

My intent was to not cut-n-paste the man pages, as the licenses do not
allow that.  So I summarized the man pages into my notes, and at a later
date, confirmed those notes against the kernel sources, and wrote my
text.

So there's no intent to match or not match the man pages, just intent to
keep the work separated enough to not cause copyright problems.

>> +@item MAP_FIXED_NOREPLACE
>> +Similar to @code{MAP_FIXED} except the call will fail with
>> +@code{EEXIST} if the new mapping would overwrite an existing mapping.
>> +To test for this, specify MAP_FIXED_NOREPLACE without MAP_FIXED, and
>> +check the actual address returned.  If it does not match the address
>> +passed, then this flag is not supported.
>
> mmap(2) states that older kernels fallback to non-MAP_FIXED behavior if
> the mapping would overwrite an existing mapping, which requires to
> carefully handle the return value. Is this backward-compatibility
> handling somehow abstracted within the libc wrapper ?

The man page says that older kernels which do not support
MAP_FIXED_NOREPLACE would act as if that flag were just omitted, which
means no MAP_FIXED either.  It does not imply that there's an older
kernel that *does* support MAP_FIXED_NOREPLACE but acts differently than
today.  In either case, testing the returned address to see if it
matches the desired one is the correct response.

There's no special backwards compatibility for mmap() in glibc, other
than to call mmap2 instead of mmap if available.

>> +@item MAP_POPULATE
>> +@itemx MAP_NONBLOCK
>> +These two are opposites.  @code{MAP_POPULATE} is a hint that requests
>> +that the kernel read-ahead a file-backed mapping, causing more pages
>> +to be mapped before they're needed.  @code{MAP_NONBLOCK} is a hint
>> +that requests that the kernel @emph{not} attempt such, only mapping
>> +pages when they're actually needed.  Note that neither of these hints
>> +affects future paging activity, use @code{mlock} if such needs to be
>> +controlled.
>
> This explanation does not match my understanding of the mmap(2) man
> page. MAP_NONBLOCK appears to be only meaningful in conjunction _with_
> MAP_POPULATE. I suspect the goal here when those are combined is to
> opportunistically populate the page table entries when those do not
> require read-ahead from a file (AFAIU).

Sigh ;-)

>> +
>> +@item MAP_NORESERVE
>> +Asks the kernel to not reserve physical backing for a mapping.
>
> What is "physical backing" ? I guess that you mean not backed by a swap
> block device (or anything that requires I/O), but I am not sure that
> "physical backing" conveys this clearly.

I'll reword this some.

>> +@item MAP_SYNC
>> +This flag is used to map persistent memory devices into the running
>> +program in such a way that writes to the mapping are immediately
>> +written to the device as well.  Unlike most other flags, this one will
>> +fail unless @code{MAP_SHARED_VALIDATE} is also given.
>
> Note that this wording is misleading. Users of persistent memory devices
> need to issue explicit "flush" instructions to ensure that writes are
> made persistent to the device. The MAP_SYNC merely guarantees that
> memory mappings within a file on a dax-enabled filesystem will appear
> at the same file offset after a crash/reboot. It goes not guarantee
> anything about write persistence.

  "This flag is supported only for files supporting DAX (direct mapping
   of persistent memory)"

  "it will be visible in the same file at the same offset even after the
   system crashes or is rebooted."

That sounds like persistence to me?

>> +@item EAGAIN
>> +
>> +The system has temporarily run out of resources.
>
> or file has been locked.

I was asked to avoid mentioning certiain types of locks that glibc
chooses not to support...

>> +@item EBADF
>> +
>> +The @var{fd} passes is invalid, and a valid file descriptor is
>
> passes -> passed ?

Sigh ;-)

>> -@item ENODEV
>> -
>> -This file is of a type that doesn't support mapping.
>> +There is not enough memory for the operation, the process is out of
>> +address space, or there are too many mappings.  On Linux, the maximum
>> +number of mappings can be controlled via
>> +@file{/proc/sys/vm/max_map_count} or, if your OS supports it, via
>> +the @code{vm.max_map_count} @code{sysctl} setting.
>
> Also getrlimit(2) RLIMIT_DATA exceeded, or @addr exceeds virtual address
> space of the CPU.

Noted.


>> +@item EPERM
>> +
>> +@code{PROT_EXEC} was requested but the file is on a filesystem that
>> +was mounted with execution denied.
>
> Also operation was prevented by a file seal (fcntl(2)).
> Also MAP_HUGETLB flag was specified, but the caller was not priviledged.

Noted.



More information about the Libc-alpha mailing list