Be more precise about the maximum number of segments per list block

UINT16_MAX would be just over a disk block, and allocating another
3.93k for a single additional segment does not make sense.

	(gdb) p /x sizeof(struct fellow_disk_seg) * 65534 +
		sizeof(struct fellow_disk_seglist)
	$7 = 0x37ffd0

Also fix a potential overflow, where a uint16_t was incremented after
clamping to UINT16_MAX.
parent a0f2bb17
......@@ -296,6 +296,22 @@ struct fellow_disk_seglist {
struct fellow_disk_seg segs[];
};
/* A good maximum number of segments per seglist is _just_ under
* 1<<16
*
* formula:
* size of 1<<16 seg plus the seglist
* rounded down to a fellow block
* minus the seglist
* devided by size of the seg
*/
#define FELLOW_DISK_SEGLIST_MAX_SEGS /* 65534 */ \
(((((sizeof(struct fellow_disk_seg) << 16) + \
sizeof(struct fellow_disk_seglist)) & ~FELLOW_BLOCK_ALIGN) - \
sizeof(struct fellow_disk_seglist)) / \
sizeof(struct fellow_disk_seg))
#define fellow_disk_seglist_size(fdsl, lsegs) \
(sizeof *fdsl + lsegs * sizeof *fdsl->segs)
......@@ -1998,9 +2014,12 @@ fellow_busy_obj_alloc(struct fellow_cache *fc,
assert(dsk_sz > asz);
sz = ((dsk_sz - asz) + sizeof(struct fellow_disk_seg))
/ sizeof(struct fellow_disk_seg);
assert(sz <= FELLOW_DISK_SEGLIST_MAX_SEGS);
assert(sz <= UINT16_MAX);
ldsegs = (uint16_t)sz;
// DBG("-> %u embedded segs", ldsegs);
// uring has signed 32bit length
assert(dsk_sz <= FIO_MAX);
......@@ -2189,15 +2208,14 @@ fellow_body_seglist_alloc(struct fellow_busy *fbo,
if (fbo->grown) {
sz = fbo->fc->tune->objsize_max - fbo->sz_dskalloc;
sz >>= MIN_FELLOW_BITS;
sz++;
} else {
sz = fbo->sz_estimate - fbo->sz_returned;
sz >>= chunk_exponent;
}
if (sz > UINT16_MAX)
sz = UINT16_MAX;
sz++;
if (sz > FELLOW_DISK_SEGLIST_MAX_SEGS)
sz = FELLOW_DISK_SEGLIST_MAX_SEGS;
ldsegs = (uint16_t)sz;
ldsegs++;
sz = fellow_disk_seglist_size(fdsl, ldsegs);
......@@ -2210,7 +2228,8 @@ fellow_body_seglist_alloc(struct fellow_busy *fbo,
assert(sz > sizeof *fdsl);
sz -= sizeof *fdsl;
sz /= sizeof *fdsl->segs;
assert(sz <= UINT16_MAX);
if (sz > UINT16_MAX)
sz = UINT16_MAX;
ldsegs = (uint16_t)sz;
reqs = BUDDY_REQS_STK(fbo->fc->membuddy, 2);
......@@ -5519,6 +5538,8 @@ t_cache(unsigned chksum)
DBGSZ(fellow_disk_seg);
DBGSZ(fellow_disk_seglist);
DBG("FELLOW_DISK_SEGLIST_MAX_SEGS %zu", FELLOW_DISK_SEGLIST_MAX_SEGS);
assert(FELLOW_DISK_SEGLIST_MAX_SEGS <= UINT16_MAX);
DBGSZ(fellow_disk_obj);
DBGSZ(fellow_cache_seg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment