From nobody Thu Apr 16 06:06:35 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fx6wD1qrWz6Z0gn for ; Thu, 16 Apr 2026 06:06:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fx6wC2Ts2z3jpH for ; Thu, 16 Apr 2026 06:06:35 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776319595; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jW1knxMdhspAyvDPZer/VSItCAj96Zxp7aQs/5xbE2k=; b=oPZ9NaSPeNJITL+j+9sSVzz27RbSafwz5E1M6BFIg8E5+maMcowaZazfJWTx6gHgYSf2zK V3fIUFi8DbiEjKxb6JzKf9gGUbcgYKXqW7//WyY3JGrh7rkwVM3rDS4UziIPVziSP1kbsl cWD/1ZkCP7Iz4fZdf2OG6dAVBxw5w1FuVVJ+xRRuL/IVPfB1lEsNEwC3xWgcwcobbF0ylv Phx7ZffNSqmuJR2PcNfnAaJZPPyfdKZAos4B4x2SPQfT9tfrrzGARBsLLq93TuVAbcMRRW IYgXiHQvEP7tIPHGIzR9La5Y5P5AhcX6pkYRkGv1HsSevY8ECeosSRtUhpXFgQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1776319595; a=rsa-sha256; cv=none; b=GwImXeXTFkBY7heHU1zxwhiiv3/CPqnUOVLxUAOGhizj6S/L4mu0VxG6+mEncpr45TPwfe RiTPTVG+1L66R6g4o+Ze1VNh34bZBImgq2J6LG75nwaenP52Xut2LoHr5pZSkj/788tFXp cgu3k0uiBQniCujFqrQRnM1ke6/5ULwNfBfhryhm9SFjV9V0iSLoqmpyFr3yo9vhWQYxvk oTXbhuUuo3pyJn3zboKM9X7Zbru1gnYROCli7cYg3JxZoZO/3qOZtmrbhgM6JFVm43dW/a HzpvXsJgR0V+YoLPGiDMDmO4o2sse5lWcNKK5zTwi00PXOsiJuOYzgmitnrykw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776319595; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jW1knxMdhspAyvDPZer/VSItCAj96Zxp7aQs/5xbE2k=; b=ena03EpQHuJ+FDjEYSz6hK+XuvntPDSLJD8dIe/3JMOE9H52CVc0SKbEhb91pVaqAzq9SH RkdKIEjEUtXvLUh7twz+HSipUtrC7OI3fqbCoRawX7D6sH/irxvGG2PWY7kZf0wPWoyQWl vExSwWrOhqJSd6SfydBLL+99zaKA5NlrqL27u9V6HTVrJZmFy4n+Fj3hTqsMFgmSx9iMRv NLCYn4WlQBldCPXmSNi8RTqgbMl3zp8n+n26DeYr0Dh56d2gatWfPARJ8inN4Rc7n32Ge8 OHYh/wy1VKZCsFx8/bXkmtyOSlx8rrghqI8gwm9l0LGRmsWSAiUs+MGRylyEow== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fx6wC210Mzvwv for ; Thu, 16 Apr 2026 06:06:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3d24b by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 16 Apr 2026 06:06:35 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Kristofer Peterson From: Warner Losh Subject: git: e75b324c93a1 - main - kern_descrip.c: Clarify allocation and freeing of fd map in fdgrowtable() List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e75b324c93a14ab68d79d9247943ae10da184657 Auto-Submitted: auto-generated Date: Thu, 16 Apr 2026 06:06:35 +0000 Message-Id: <69e07c6b.3d24b.11fc05c1@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=e75b324c93a14ab68d79d9247943ae10da184657 commit e75b324c93a14ab68d79d9247943ae10da184657 Author: Kristofer Peterson AuthorDate: 2026-02-18 13:56:53 +0000 Commit: Warner Losh CommitDate: 2026-04-16 06:05:22 +0000 kern_descrip.c: Clarify allocation and freeing of fd map in fdgrowtable() When expanding a file table, the condition for allocating a new map is NDSLOTS(nnfiles) > NDSLOTS(onfiles) whereas for freeing the old map is NDSLOTS(onfiles) > NDSLOTS(NDFILE). If a previously expanded file table were to be expanded slightly again such that the map did not need to be increased, then fdgrowtable could still free the current map. This does not happen currently as nnfiles is rounded up to a multiple of NDENTRIES at the beginning of fdgrowtable() so that every enlargement after the first enlargement will always require a larger map. Though the logic is currently correct, it is unclear and should the earlier rounding up of nnfiles be relaxed or remove, the logic would be incorrect. This patch therefore adds comments and invariants checking the size of the table and map, and updates the map free condition so that it is absolutely clear that the old map will only be deallocated if a new map has been allocated. Signed-off-by: Kristofer Peterson Reviewed by: kib, kevans Pull Request: https://github.com/freebsd/freebsd-src/pull/2029 --- sys/kern/kern_descrip.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 2fa0621bdfca..69985c39c3c0 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2006,6 +2006,21 @@ fdgrowtable(struct filedesc *fdp, int nfd) NDSLOTTYPE *nmap, *omap; KASSERT(fdp->fd_nfiles > 0, ("zero-length file table")); + KASSERT(fdp->fd_nfiles >= NDFILE, ("file table of length %d shorter " + "than NDFILE (%d)", fdp->fd_nfiles, NDFILE)); + KASSERT(fdp->fd_nfiles == NDFILE || fdp->fd_nfiles % NDENTRIES == 0, + ("file table of length %d should be multiple of NDENTRIES (%lu)", + fdp->fd_nfiles, NDENTRIES)); + KASSERT((fdp->fd_nfiles == NDFILE) == ((intptr_t)fdp->fd_files - + offsetof(struct filedesc0, fd_dfiles) == (intptr_t)fdp - + offsetof(struct filedesc0, fd_fd)), ("file table of length %d " + "should have %s table", fdp->fd_nfiles, fdp->fd_nfiles == NDFILE ? + "initial" : "dynamic")); + KASSERT((NDSLOTS(fdp->fd_nfiles) <= NDSLOTS(NDFILE)) == ((intptr_t) + fdp->fd_map - offsetof(struct filedesc0, fd_dmap) == (intptr_t)fdp - + offsetof(struct filedesc0, fd_fd)), ("file table of length %d " + "should have %s map", fdp->fd_nfiles, NDSLOTS(fdp->fd_nfiles) <= + NDSLOTS(NDFILE) ? "initial" : "dynamic")); /* save old values */ onfiles = fdp->fd_nfiles; @@ -2035,9 +2050,19 @@ fdgrowtable(struct filedesc *fdp, int nfd) onfiles * sizeof(ntable->fdt_ofiles[0])); /* - * Allocate a new map only if the old is not large enough. It will - * grow at a slower rate than the table as it can map more - * entries than the table can hold. + * Allocate a new map only if the old one is not large enough. + * + * The initial struct filedesc0 object contains a table and map sized + * for NDFILE (20) entries which means the initial map can accomodate + * up to NDENTRIES (32 or 64) before requiring reallocation. + * + * As the new table size (nnfiles) is always rounded up to a multiple + * of NDENTRIES, the map will be fully utilised following the first + * enlargement, whether it is still the initial map (which will be the + * case if nnfiles == NDENTRIES) or if a new one that has has been + * allocated (which will be the case if nnfiles == X*NDENTRIES for some + * X > 1). In either case, subsequent enlargements will always allocate + * a new map to go along with the new table. */ if (NDSLOTS(nnfiles) > NDSLOTS(onfiles)) { nmap = malloc(NDSLOTS(nnfiles) * NDSLOTSIZE, M_FILEDESC, @@ -2045,6 +2070,8 @@ fdgrowtable(struct filedesc *fdp, int nfd) /* copy over the old data and update the pointer */ memcpy(nmap, omap, NDSLOTS(onfiles) * sizeof(*omap)); fdp->fd_map = nmap; + } else { + nmap = NULL; } /* @@ -2085,9 +2112,10 @@ fdgrowtable(struct filedesc *fdp, int nfd) /* * The map does not have the same possibility of threads still * holding references to it. So always free it as long as it - * does not reference the original static allocation. + * does not reference the original static allocation and a new + * map was allocated. */ - if (NDSLOTS(onfiles) > NDSLOTS(NDFILE)) + if (nmap != NULL && NDSLOTS(onfiles) > NDSLOTS(NDFILE)) free(omap, M_FILEDESC); }