Fix rangelock test for growing block size

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 <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com>
Signed-off-by: Mark Maybee <mark.maybee@perforce.com>
Closes #18046
Closes #18064
This commit is contained in:
Mark Maybee 2025-12-18 10:23:38 -07:00 committed by GitHub
parent 051a8c7494
commit 7ff329ac2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 8 additions and 6 deletions

View File

@ -121,11 +121,12 @@ zfs_rangelock_cb(zfs_locked_range_t *new, void *arg)
}
/*
* If we need to grow the block size then lock the whole file range.
* If we might grow the block size then lock the whole file range.
* NB: this test should match the check in zfs_grow_blocksize
*/
uint64_t end_size = MAX(zp->z_size, new->lr_offset + new->lr_length);
if (end_size > zp->z_blksz && (!ISP2(zp->z_blksz) ||
zp->z_blksz < ZTOZSB(zp)->z_max_blksz)) {
if (zp->z_size <= zp->z_blksz && end_size > zp->z_blksz &&
(!ISP2(zp->z_blksz) || zp->z_blksz < ZTOZSB(zp)->z_max_blksz)) {
new->lr_offset = 0;
new->lr_length = UINT64_MAX;
}

View File

@ -95,11 +95,12 @@ zfs_rangelock_cb(zfs_locked_range_t *new, void *arg)
}
/*
* If we need to grow the block size then lock the whole file range.
* If we might grow the block size then lock the whole file range.
* NB: this test should match the check in zfs_grow_blocksize
*/
uint64_t end_size = MAX(zp->z_size, new->lr_offset + new->lr_length);
if (end_size > zp->z_blksz && (!ISP2(zp->z_blksz) ||
zp->z_blksz < ZTOZSB(zp)->z_max_blksz)) {
if (zp->z_size <= zp->z_blksz && end_size > zp->z_blksz &&
(!ISP2(zp->z_blksz) || zp->z_blksz < ZTOZSB(zp)->z_max_blksz)) {
new->lr_offset = 0;
new->lr_length = UINT64_MAX;
}