Skip to content

Fix rangelock test for growing block size - #18064

Merged
behlendorf merged 1 commit into
openzfs:masterfrom
mmaybee:rangelock
Dec 18, 2025
Merged

behlendorf merged 1 commit into
openzfs:masterfrom
mmaybee:rangelock

Conversation

@mmaybee

@mmaybee mmaybee commented Dec 17, 2025 •

Copy link
Copy Markdown
Contributor

Motivation and Context

If the file already has more than one block, then the current block size cannot change. But if the file block size is less than the maximum block size supported by the file system, and there are multiple blocks in the file, the current code will almost always extend the rangelock to its maximum size. This means that all writes become serialized and even reads are slowed as they will more often contend with writes.

See issue: #18046

Description

This commit adjusts the test so that we will not lock the entire range if there is more than one block in the file already.

How Has This Been Tested?

Verified via some lock debugging that the new test works as intended.

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)
  • Quality assurance (non-breaking change which makes the code more robust against bugs)
  • 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:

If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Signed-off-by: Mark Maybee 
Copilot AI review requested due to automatic review settings December 17, 2025 18:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a performance regression in the rangelock mechanism for growing block sizes. The issue occurred when files with multiple blocks (but block size smaller than the filesystem maximum) would unnecessarily lock the entire file range during writes, causing all writes to serialize and reads to slow down due to lock contention.

Key Changes:

  • Added a check to prevent extending rangelock to maximum size when a file already has more than one block
  • Updated comments to clarify the conditional logic and reference the corresponding check in zfs_grow_blocksize

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
module/os/linux/zfs/zfs_znode_os.c Added zp->z_size <= zp->z_blksz condition to prevent unnecessary full-file locking for multi-block files
module/os/freebsd/zfs/zfs_znode_os.c Applied identical rangelock fix for FreeBSD implementation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mmaybee
mmaybee requested a review from amotin December 17, 2025 18:25
@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label Dec 17, 2025

@behlendorf behlendorf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find, this over-locking case when the default recordsize changes on a dataset was subtle. The fix looks good, and thanks for updating the comment to reference the check in zfs_grow_blocksize().

Related to this it looks like we should consider moving zfs_rangelock_cb(), zfs_grow_blocksize(), and perhaps some other functions back in to the common code. They're effectively identical. That's something for its own PR though.

@amotin amotin added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels Dec 18, 2025
@behlendorf
behlendorf merged commit 7ff329a into openzfs:master Dec 18, 2025
40 of 42 checks passed
amotin pushed a commit to amotin/zfs that referenced this pull request Jan 29, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
mcmilk pushed a commit to mcmilk/zfs that referenced this pull request Jan 31, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
amotin pushed a commit to amotin/zfs that referenced this pull request Feb 3, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
lundman pushed a commit to openzfsonosx/openzfs-fork that referenced this pull request Feb 5, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
tonyhutter pushed a commit that referenced this pull request Feb 5, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes #18046
Closes #18064
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Feb 23, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
lundman pushed a commit to openzfsonwindows/openzfs that referenced this pull request Feb 23, 2026
If the file already has more than one block, then the current
block size cannot change. But if the file block size is less
than the maximum block size supported by the file system, and
there are multiple blocks in the file, the current code will
almost always extend the rangelock to its maximum size.
This means that all writes become serialized and even reads
are slowed as they will more often contend with writes. This
commit adjusts the test so that we will not lock the entire
range if there is more than one block in the file already.

Reviewed-by: Brian Behlendorf 
Reviewed-by: Alexander Motin 
Signed-off-by: Mark Maybee 
Closes openzfs#18046
Closes openzfs#18064
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.

4 participants