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:
parent
4840f023af
commit
db499e68f9
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue