kern: osd: stop downsizing arrays when the last slot deregisters

It was noted in D41404 that these reallocations aren't actually
guaranteed to succeed, despite assertions to the contrary.  We're
talking relatively small allocations, so just free up the individual
slot to be reused later as needed.

Note that this doesn't track the last active slot as of this moment, but
this could be done later if we find it's worth the complexity for what
little that would allow to be optimized (osd_call, slightly).

While we're here, fix the debug message that indicates which slot we
just allocated when we find an unused one; the slot # is actually one
higher than the index.

Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D41409
This commit is contained in:
Kyle Evans 2023-08-17 23:05:55 -05:00
parent 214e3e09b3
commit a76629cb03

View file

@ -112,7 +112,7 @@ osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
for (i = 0; i < osdm[type].osd_ntslots; i++) {
if (osdm[type].osd_destructors[i] == NULL) {
OSD_DEBUG("Unused slot found (type=%u, slot=%u).",
type, i);
type, i + 1);
break;
}
}
@ -166,32 +166,18 @@ osd_deregister(u_int type, u_int slot)
LIST_FOREACH_SAFE(osd, &osdm[type].osd_list, osd_next, tosd)
do_osd_del(type, osd, slot, 1);
mtx_unlock(&osdm[type].osd_list_lock);
/*
* Set destructor to NULL to free the slot.
* Set destructor to NULL to free the slot. We don't bother actually
* freeing any memory here because we'll gracefully reuse any freed
* slots, and reallocating the arrays as a smaller chunk of memory isn't
* actually guaranteed to succeed. As such, we'll err on the side of
* caution and just leave it be since these are generally modestly sized
* allocations.
*/
osdm[type].osd_destructors[slot - 1] = NULL;
if (slot == osdm[type].osd_ntslots) {
osdm[type].osd_ntslots--;
osdm[type].osd_destructors = realloc(osdm[type].osd_destructors,
sizeof(osd_destructor_t) * osdm[type].osd_ntslots, M_OSD,
M_NOWAIT | M_ZERO);
if (osdm[type].osd_nmethods != 0)
osdm[type].osd_methods = realloc(osdm[type].osd_methods,
sizeof(osd_method_t) * osdm[type].osd_ntslots *
osdm[type].osd_nmethods, M_OSD, M_NOWAIT | M_ZERO);
/*
* We always reallocate to smaller size, so we assume it will
* always succeed.
*/
KASSERT(osdm[type].osd_destructors != NULL &&
(osdm[type].osd_nmethods == 0 ||
osdm[type].osd_methods != NULL), ("realloc() failed"));
OSD_DEBUG("Deregistration of the last slot (type=%u, slot=%u).",
type, slot);
} else {
OSD_DEBUG("Slot deregistration (type=%u, slot=%u).",
type, slot);
}
OSD_DEBUG("Slot deregistration (type=%u, slot=%u).", type, slot);
rm_wunlock(&osdm[type].osd_object_lock);
sx_xunlock(&osdm[type].osd_module_lock);
}