Skip to content

pagecache: report page-writeback errors from sync() by return value - #1483

Open
gburd wants to merge 2 commits into
cloudius-systems:masterfrom
gburd:pr/pagecache-munmap-sync-nothrow
Open

pagecache: report page-writeback errors from sync() by return value#1483
gburd wants to merge 2 commits into
cloudius-systems:masterfrom
gburd:pr/pagecache-munmap-sync-nothrow

Conversation

@gburd

@gburd gburd commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

pagecache::sync() threw a C++ error when a page writeback (cached_page_write::writeback()) failed. Its only caller is the munmap / msync path: vfs_file::sync(), invoked from mmu::file_vma::sync(), which already converts the outcome to a return value and surfaces any error through its own sys_fsync() tail. The fsync(2) syscall uses a separate VOP_FSYNC path and never relied on this throw, so no caller depended on the exception.

Throwing from the munmap path is both unnecessary and fragile: raising an exception during munmap() can abort when the C++ unwinder cannot complete in the calling context, turning a recoverable page-writeback error into a fatal abort() that takes down the whole instance.

Change

  • pagecache::sync() returns int (0 on success, or the writeback errno) instead of throwing.
  • vfs_file::sync() consumes the return value; mmu::file_vma::sync() continues to report the error via sys_fsync().
  • The declaration in include/osv/pagecache.hh is updated to match.

Behavior is unchanged on success. On a writeback error, sync() now returns the errno rather than throwing, and the page is left marked dirty for retry exactly as before.

gburd added 2 commits August 27, 2026 04:35
pagecache::sync() threw a C++ error when a page writeback failed. Its only
caller is the munmap / msync path (vfs_file::sync, invoked from
mmu::file_vma::sync), which already converts the outcome to a return value and
surfaces any error through its own sys_fsync() tail. No caller depended on the
exception.

Throwing from that path is both unnecessary and fragile: raising an exception
during munmap can abort when the C++ unwinder cannot complete in the calling
context, turning a recoverable writeback error into a fatal abort() that takes
down the whole instance. Return the writeback errno from sync() instead;
vfs_file::sync() consumes it and file_vma::sync() continues to report the
error via sys_fsync().

Behavior is unchanged on success. On writeback error, sync() now returns the
errno rather than throwing.
The base file::sync(off_t,off_t) threw make_error(ENOSYS). It is called from
the munmap / msync page-writeback path (mmu::file_vma::sync -> _file->sync()),
so unmapping a file-backed mapping whose file type does not override sync()
raised a C++ exception during munmap(). That exception cannot be unwound from
this path (it reaches __cxa_throw / _Unwind_RaiseException and bottoms out in
abort()), taking down the instance.

A file type that does not implement sync() has no cached writable pages to
flush, so the correct default is to do nothing. vfs_file, the only type that
caches writable file pages, overrides sync() with the real page-cache
writeback (which reports errors by return value, per the previous commit).
Make the default a no-op so munmap of any other file-backed mapping cannot
raise an exception.

Companion to the pagecache::sync() change: together they remove all C++
throws from the munmap page-writeback path.
@gburd

gburd commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Added a companion commit: the base file::sync() (the virtual default in include/osv/file.h) also threw make_error(ENOSYS) and is reached from the same munmap page-writeback path (mmu::file_vma::sync -> _file->sync()). Unmapping a file-backed mapping whose file type does not override sync() therefore raised an exception during munmap() that cannot be unwound from that path and bottoms out in abort(). A file type with no cached writable pages has nothing to flush, so the default is now a no-op. Together with the pagecache change this removes all C++ throws from the munmap writeback path.

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