Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.1.12 backport] Fix buffered/direct/mmap I/O race #14750

Merged

Conversation

robn
Copy link
Member

@robn robn commented Apr 15, 2023

Description

Backporting #14498 and #14534 to 2.1.

How Has This Been Tested?

Compiles OK. Test suite will do the rest.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

@ryao
Copy link
Contributor

ryao commented Apr 16, 2023

We should also include dd108f5, which fixes the static analyzer complaint about what should be a real bug that occurs after this is merged.

@robn
Copy link
Member Author

robn commented Apr 16, 2023

We should also include dd108f5, which fixes the static analyzer complaint about what should be a real bug that occurs after this is merged.

Good call! I've picked that commit and pushed it here. Thanks!

@behlendorf
Copy link
Contributor

Can you rebase this on the new zfs-2.1.12-staging. branch.

@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label Apr 20, 2023
behlendorf and others added 2 commits April 21, 2023 07:45
When a page is faulted in for memory mapped I/O the page lock
may be dropped before it has been read and marked up to date.
If a buffered read encounters such a page in mappedread() it
must wait until the page has been updated. Failure to do so
will result in a panic on debug builds and incorrect data on
production builds.

The critical part of this change is in mappedread() where pages
which are not up to date are now handled. Additionally, it
includes the following simplifications.

- zfs_getpage() and zfs_fillpage() could be passed an array of
  pages. This could be more efficient if it was used but in
  practice only a single page was ever provided. These
  interfaces were simplified to acknowledge that.

- update_pages() was modified to correctly set the PG_error bit
  on a page when it cannot be read by dmu_read().

- Setting PG_error and PG_uptodate was moved to zfs_fillpage()
  from zpl_readpage_common(). This is consistent with the
  handling in update_pages() and mappedread().

- Minor additional refactoring to comments and variable
  declarations to improve readability.

- Add a test case to exercise concurrent buffered, direct,
  and mmap IO to the same file.

- Reduce the mmap_sync test case default run time.

Reviewed-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Reviewed-by: Brian Atkinson <batkinson@lanl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes openzfs#13608
Closes openzfs#14498
After 89cd219 was merged, Clang's
static analyzer began complaining about a dead assignment in
`zfs_fillpage()`. Upon inspection, I noticed that the dead assignment
was because we are not using the calculated io_len that we should use to
avoid asking the DMU to read past the end of a file. This should result
in `dmu_buf_hold_array_by_dnode()` calling `zfs_panic_recover()`.

This issue predates 89cd219, but its
simplification of zfs_fillpage() eliminated the only use of the
assignment to io_len, which made Clang's static analyzer complain about
the issue.

Also, as a precaution, we add an assertion that io_offset < i_size. If
this ever fails, bad things will happen. Otherwise, we are blindly
trusting the kernel not to give us invalid offsets. We continue to
blindly trust it on non-debug kernels.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Brian Atkinson <batkinson@lanl.gov>
Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Closes openzfs#14534
@robn robn force-pushed the buffered-mmap-race-backport-2.1 branch from 7ac738c to 71ecb8b Compare April 20, 2023 21:57
@robn robn changed the title [2.1.11 backport] Fix buffered/direct/mmap I/O race [2.1.12 backport] Fix buffered/direct/mmap I/O race Apr 20, 2023
@robn robn changed the base branch from zfs-2.1.11-staging to zfs-2.1.12-staging April 20, 2023 21:58
@robn
Copy link
Member Author

robn commented Apr 20, 2023

@behlendorf done, thanks.

@behlendorf behlendorf added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels Apr 20, 2023
@behlendorf behlendorf merged commit 4a5950a into openzfs:zfs-2.1.12-staging Apr 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Accepted Ready to integrate (reviewed, tested)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants