Skip to content

Commit

Permalink
microzap: set hard upper limit of 1M
Browse files Browse the repository at this point in the history
The count of chunks in a microzap block is stored as an int16_t
(zap_num_chunks). Each chunk is 64 bytes, and the first is used to store
a header, so there are 32767 usable chunks, which is just under 2M. 1M
is the largest power-2-rounded block size under 2M, so we must set the
limit there.

If it goes higher, the loop in mzap_addent can overflow and fall into
the PANIC case.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Signed-off-by: Rob Norris <[email protected]>
  • Loading branch information
robn committed Dec 19, 2024
1 parent ab7cbbe commit 8b09779
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions module/zfs/zap_micro.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,25 @@
* machinery to understand not to try to split a microzap block).
*
* If large_microzap is enabled, this value will be clamped to
* spa_maxblocksize(). If not, it will be clamped to SPA_OLD_MAXBLOCKSIZE.
* spa_maxblocksize(), up to 1M. If not, it will be clamped to
* SPA_OLD_MAXBLOCKSIZE.
*/
static int zap_micro_max_size = SPA_OLD_MAXBLOCKSIZE;

/*
* The 1M upper limit is necessary because the count of chunks in a microzap
* block is stored as an int16_t (zap_num_chunks). Each chunk is 64 bytes, and
* the first is used to store a header, so there are 32767 usable chunks, which
* is just under 2M. 1M is the largest power-2-rounded block size under 2M, so
* we must set the limit there.
*/
#define MZAP_MAX_SIZE (1048576)

uint64_t
zap_get_micro_max_size(spa_t *spa)
{
uint64_t maxsz = P2ROUNDUP(zap_micro_max_size, SPA_MINBLOCKSIZE);
uint64_t maxsz = MIN(MZAP_MAX_SIZE,
P2ROUNDUP(zap_micro_max_size, SPA_MINBLOCKSIZE));
if (maxsz <= SPA_OLD_MAXBLOCKSIZE)
return (maxsz);
if (spa_feature_is_enabled(spa, SPA_FEATURE_LARGE_MICROZAP))
Expand Down Expand Up @@ -2031,5 +2042,6 @@ EXPORT_SYMBOL(zap_cursor_init_serialized);
EXPORT_SYMBOL(zap_get_stats);

ZFS_MODULE_PARAM(zfs, , zap_micro_max_size, INT, ZMOD_RW,
"Maximum micro ZAP size, before converting to a fat ZAP, in bytes");
"Maximum micro ZAP size before converting to a fat ZAP, "
"in bytes (max 1M)");
#endif

0 comments on commit 8b09779

Please sign in to comment.