Skip to content

mm: implement mremap(2) - #1412

Closed
gburd wants to merge 1 commit into
cloudius-systems:masterfrom
gburd:pr/mremap
Closed

mm: implement mremap(2)#1412
gburd wants to merge 1 commit into
cloudius-systems:masterfrom
gburd:pr/mremap

Conversation

@gburd

@gburd gburd commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What

Implements mremap(2), which was missing entirely on OSv: it was not in the
syscall table and had no libc entry point, so applications and allocators that
resize an mmap region failed (glibc/musl realloc of an mmap-backed chunk calls
the internal __mremap).

How

mmu::mremap() (core/mmu.cc) is built on the existing VMA machinery and the
public, self-locking map_anon()/map_file()/munmap() primitives. It handles
a single, wholly mapped source vma (Linux likewise requires the old range to
fall within one mapping; a range spanning several vmas or a hole yields
EFAULT):

  • shrink / no-op: drop the tail in place, address unchanged;
  • grow in place: when the region immediately after the source is free;
  • grow with MREMAP_MAYMOVE: allocate a new region of the new size, migrate
    the contents (anonymous: copy; file-backed: remap the file at the same offset
    so the grown tail is served by the fault path with no copy), then unmap the old
    range.

The source vma is inspected once under vma_list_mutex to snapshot its
perm/flags/type/file/offset and whether its tail is free, so the rest of the
function can call the self-locking primitives without nesting the non-recursive
vma write lock.

MREMAP_FIXED is not supported yet and returns EINVAL rather than doing the
wrong thing; the anonymous and file-backed paths cover the callers we have.

Wired as syscall SYS_mremap (via long_mremap, mirroring long_mmap since the
return value is a pointer) with a matching tracepoint, plus the libc
mremap()/__mremap() entry points, and both symbols exported from
libc.so.6 and ld-musl.so.1.

Testing

tests/tst-mremap.cc covers grow, shrink, in-place-blocked (ENOMEM without
MREMAP_MAYMOVE), file-backed move, and the EINVAL/EFAULT error paths. It
passes on OSv under KVM and on native Linux (semantics match). tst-mmap
continues to pass, so there is no regression in the VMA path.

mremap() was missing entirely on OSv: it was not in the syscall table and
had no libc entry point, so applications and allocators (glibc/musl
realloc of mmap-backed chunks calls the internal __mremap) that resize an
mmap region failed.

Add mmu::mremap() in core/mmu.cc, built on the existing VMA machinery and
the public self-locking map_anon()/map_file()/munmap() primitives. It
handles a single, wholly mapped source vma (Linux requires the old range
to fall in one mapping too; a range spanning several vmas or a hole yields
EFAULT):

- shrink / no-op: drop the tail in place, address unchanged;
- grow in place when the region immediately after the source is free;
- grow with MREMAP_MAYMOVE: allocate a new region of the new size, migrate
  the contents (anon: copy; file-backed: remap the file at the same offset
  so the grown tail is served by the fault path with no copy), then unmap
  the old range.

The source vma is inspected once under vma_list_mutex to snapshot its
perm/flags/type/file/offset and whether its tail is free, so the rest of
the function can call the self-locking primitives without nesting the
non-recursive vma write lock.

MREMAP_FIXED is not supported yet and returns EINVAL rather than doing the
wrong thing; the anon and file-backed paths cover the callers we have.

Wire it as syscall SYS_mremap (via long_mremap, mirroring long_mmap since
the return value is a pointer) with a matching tracepoint, add the libc
mremap()/__mremap() entry points, and export both symbols from libc.so.6
and ld-musl.so.1.

Add tests/tst-mremap.cc covering grow, shrink, in-place-blocked (ENOMEM
without MREMAP_MAYMOVE), file-backed move, and the EINVAL/EFAULT error
paths. Passes on OSv under KVM and on native Linux (semantics match).
tst-mmap continues to pass (no regression in the VMA path).
@gburd gburd closed this Jul 13, 2026
@gburd
gburd deleted the pr/mremap branch July 13, 2026 11:17
@gburd

gburd commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1432 (rebased onto current master; GitHub auto-closed this one when the branch was updated). Please review #1432 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant