Repository navigation
Fix rangelock test for growing block size - #18064
Conversation
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
There was a problem hiding this comment.
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.
behlendorf
left a comment
There was a problem hiding this comment.
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.
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes #18046 Closes #18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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 BehlendorfReviewed-by: Alexander Motin Signed-off-by: Mark Maybee Closes openzfs#18046 Closes openzfs#18064
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
Checklist:
Signed-off-by.