Overflowing refreservation is bad

Someone came to me and pointed out that you could pretty
readily cause the refreservation calculation to exceed
2**64, given the 2**17 multiplier in it, and produce
refreservations wildly less than the actual volsize in cases where
it should have failed.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rich Ercolani <rincebrain@gmail.com>
Closes #15996
This commit is contained in:
Rich Ercolani 2024-04-29 14:32:49 -04:00 committed by GitHub
parent 4840f023af
commit db499e68f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 14 additions and 1 deletions

View File

@ -5565,8 +5565,21 @@ volsize_from_vdevs(zpool_handle_t *zhp, uint64_t nblocks, uint64_t blksize)
/* /*
* Scale this size down as a ratio of 128k / tsize. * Scale this size down as a ratio of 128k / tsize.
* See theory statement above. * See theory statement above.
*
* Bitshift is to avoid the case of nblocks * asize < tsize
* producing a size of 0.
*/ */
volsize = nblocks * asize * SPA_OLD_MAXBLOCKSIZE / tsize; volsize = (nblocks * asize) / (tsize >> SPA_MINBLOCKSHIFT);
/*
* If we would blow UINT64_MAX with this next multiplication,
* don't.
*/
if (volsize >
(UINT64_MAX / (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT)))
volsize = UINT64_MAX;
else
volsize *= (SPA_OLD_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT);
if (volsize > ret) { if (volsize > ret) {
ret = volsize; ret = volsize;
} }