-
Bug
-
Resolution: Fixed
-
Medium
-
None
-
None
-
3
-
9223372036854775807
In kiblnd_fmr_pool_map():
The FastReg descriptor is removed from the free list:
list_del(&frd->frd_list);
On a short map, the function returns directly:
if (unlikely(n != rd->rd_nfrags)) { CERROR("Failed to map mr %d/%d elements\n", n, rd->rd_nfrags); return n < 0 ? n : -EINVAL; }
This return is reached before fmr->fmr_frd = frd and before fpo->fpo_map_count-. kiblnd_unmap_tx()(o2iblnd_cb.c:676-681) releases the frd only when tx>tx_fmr.fmr_frd is set (it is not).
Thus, every failed map leaks one frd (never returned to fpo_pool_list) and one fpo_map_count refcount. This has two downstream consequences:
- the pool can never be reaped in kiblnd_fmr_pool_is_idle()
if (fpo->fpo_map_count != 0) /* still in use */ return 0;
# frd exhaustion drives unbounded pool growth
Each failure drains one frd. Once fpo->fast_reg.fpo_pool_list is empty, the FastReg branch guard fails:
if (!list_empty(&fpo->fast_reg.fpo_pool_list)) { /* now false */
> falls through to rc = -EAGAIN , fpo_map_count- , retry. With every existing pool's frd list drained, every pool yields -EAGAIN → the grow path runs (fps_increasing) → a new pool is allocated and appended. Its frds get drained the same way by ongoing gapped txs → another new pool, and so on.
As a result, pool count climbs monotonically, and every drained old pool carries a non-zero leaked fpo_map_count so none are ever reclaimed. Memory and pool-list length grow without bound over a long run.