2Z; Sat, 18 Oct 2025 05:14:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1760764448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=X1nQr+4yrT6Grkb1lTDfdI7p7YMbENcrmAVR6LR/W2g=; b=rHFrH+fzNreZQBqcgrvsSY0oJu0ep2K4rfjDkx9adXt7EKOvYcDL0I4Xk3lE+xmvYSErQQ Q/m9ZfptfUSCDNZ5aOWWhX9qjDwz+IbELGIZOh08l1NcWom6TQ8+puXvyUDl59Ie5kHlPp yWXaLC95s2AeXJoWg9NR5NZwKHeNuRvhhfySJkJ4m82y1HTQ4sh2KidT/8X9/qr1Z0lPIg iXDsf3EQ6j61CtjuZaix4C2d2B7wDVn849JdN+q+Cb00rTt8MyQUVXKfLiB4uj1lXYHbCB lndBsQxKzOq4aRQrRTrOr838JEu5XWD784qG7RVTWWxVS0lLCE613XYmcGYGFw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1760764448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=X1nQr+4yrT6Grkb1lTDfdI7p7YMbENcrmAVR6LR/W2g=; b=SvNUH5YVBsdaqgUrUEdspoKF62zWkxZbdi2cCUEioX1mN8LUWB8eFy8dFFo8zJ47w1Mnrj +yd/rKtRRroDBdFlWBfJYMY4dvg7rbOS81ymdItaWDP1cQvECR2f/6sydo0HO9DRfDwdDL glltkXqWxaVaFtwY7ntHPD3xBhVjatZ7PVKU0i3aHJjZywJyq3//yv0dTr1KxHEPnR7i3m TMbowYTK+OmQCOmA7GC4rfenOswaGdSn6aa6Qyx8cfA8ZNE3IdZgeHAOxXZ9pTLbx04tmw ajGWcyKjQ0j+LH5znt837GNGeNvvpUZ3MYnY3wwMIXkPBTBVCsSdIGjDue3zSA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1760764448; a=rsa-sha256; cv=none; b=EzOmg74kMMWnX/hhnCkuPkgbGcaMOSxJb6lKJ/9IAQ6+RudhxVA5hmj4d8A8IQpKTjexWE oP2wz/GEtf/ZdFvWhDxACJIe/TwAb5Vz/tRWGnRyW1q9fNA5atOSXfEVGeNrSI+rxqFnvf KYtz6Dayq8KXyNMLSlhRDR18QKYH9OI7EQJhsUyU8bGRlUcR5S7vvkA+1wJLpQ9fP65FJm uhGoeEu2Yv2A3lBSltByVmZB0eNeK47MaHma5UqenOvPBmUkdW6Iw6/1C7xhYnrNEJBy0K olKvKLXLLnfjBEMbku7x8DRExuTJu15BY8hUUgY0kdzFfKihlrA+lE7Uj1/1FA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cpVGm5wGbzBrq; Sat, 18 Oct 2025 05:14:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 59I5E80e062263; Sat, 18 Oct 2025 05:14:08 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 59I5E8Ln062260; Sat, 18 Oct 2025 05:14:08 GMT (envelope-from git) Date: Sat, 18 Oct 2025 05:14:08 GMT Message-Id: <202510180514.59I5E8Ln062260@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 1265516c5c61 - main - struct file: add DFLAG_FORK, indicate copying on fork 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: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1265516c5c610fbc0d65451140e3f17b358cd015 Auto-Submitted: auto-generated The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=1265516c5c610fbc0d65451140e3f17b358cd015 commit 1265516c5c610fbc0d65451140e3f17b358cd015 Author: Konstantin Belousov AuthorDate: 2025-08-20 19:07:43 +0000 Commit: Konstantin Belousov CommitDate: 2025-10-18 05:11:40 +0000 struct file: add DFLAG_FORK, indicate copying on fork instead of referencing or ignoring. The pass to handle copying is performed after all passable files are installed into the new file descriptor's table, since one of the future consumers of this interface (kqueue) needs all passable file descriptors already valid. After all fds are installed, the additional call for each copyable file is done to copy the underlying object. [MFC note: use fo_spares for fo_fork] Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D52045 --- sys/kern/kern_descrip.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++-- sys/sys/file.h | 4 ++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 19118eb7f275..373542d16285 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2519,10 +2519,13 @@ fdcopy(struct filedesc *fdp) { struct filedesc *newfdp; struct filedescent *nfde, *ofde; + struct file *fp; int i, lastfile; + bool fork_pass; MPASS(fdp != NULL); + fork_pass = false; newfdp = fdinit(); FILEDESC_SLOCK(fdp); for (;;) { @@ -2533,10 +2536,35 @@ fdcopy(struct filedesc *fdp) fdgrowtable(newfdp, lastfile + 1); FILEDESC_SLOCK(fdp); } - /* copy all passable descriptors (i.e. not kqueue) */ + + /* + * Copy all passable descriptors (i.e. not kqueue), and + * prepare to handle copyable but not passable descriptors + * (kqueues). + * + * The pass to handle copying is performed after all passable + * files are installed into the new file descriptor's table, + * since kqueues need all referenced file descriptors already + * valid, including other kqueues. For the same reason the + * copying is done in two passes by itself, first installing + * not fully initialized ('empty') copyable files into the new + * fd table, and then giving the subsystems a second chance to + * really fill the copied file backing structure with the + * content. + */ newfdp->fd_freefile = fdp->fd_freefile; FILEDESC_FOREACH_FDE(fdp, i, ofde) { - if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 || + const struct fileops *ops; + + ops = ofde->fde_file->f_ops; + fp = NULL; + if ((ops->fo_flags & DFLAG_FORK) != 0 && + (ofde->fde_flags & UF_FOCLOSE) == 0) { + if (ops->fo_fork(newfdp, ofde->fde_file, &fp, p1, + curthread) != 0) + continue; + fork_pass = true; + } else if ((ops->fo_flags & DFLAG_PASSABLE) == 0 || (ofde->fde_flags & UF_FOCLOSE) != 0 || !fhold(ofde->fde_file)) { if (newfdp->fd_freefile == fdp->fd_freefile) @@ -2545,11 +2573,30 @@ fdcopy(struct filedesc *fdp) } nfde = &newfdp->fd_ofiles[i]; *nfde = *ofde; + if (fp != NULL) + nfde->fde_file = fp; filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true); fdused_init(newfdp, i); } MPASS(newfdp->fd_freefile != -1); FILEDESC_SUNLOCK(fdp); + + /* + * Now handle copying kqueues, since all fds, including + * kqueues, are in place. + */ + if (__predict_false(fork_pass)) { + FILEDESC_FOREACH_FDE(newfdp, i, nfde) { + const struct fileops *ops; + + ops = nfde->fde_file->f_ops; + if ((ops->fo_flags & DFLAG_FORK) == 0 || + nfde->fde_file == NULL) + continue; + ops->fo_fork(newfdp, NULL, &nfde->fde_file, p1, + curthread); + } + } return (newfdp); } diff --git a/sys/sys/file.h b/sys/sys/file.h index c44fd0f28929..e0195c7c6c2a 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -139,6 +139,8 @@ typedef int fo_fspacectl_t(struct file *fp, int cmd, off_t *offset, off_t *length, int flags, struct ucred *active_cred, struct thread *td); typedef int fo_cmp_t(struct file *fp, struct file *fp1, struct thread *td); +typedef int fo_fork_t(struct filedesc *fdp, struct file *fp, struct file **fp1, + struct proc *p1, struct thread *td); typedef int fo_spare_t(struct file *fp); typedef int fo_flags_t; @@ -163,12 +165,14 @@ struct fileops { fo_fallocate_t *fo_fallocate; fo_fspacectl_t *fo_fspacectl; fo_cmp_t *fo_cmp; + fo_fork_t *fo_fork; fo_spare_t *fo_spares[8]; /* Spare slots */ fo_flags_t fo_flags; /* DFLAG_* below */ }; #define DFLAG_PASSABLE 0x01 /* may be passed via unix sockets. */ #define DFLAG_SEEKABLE 0x02 /* seekable / nonsequential */ +#define DFLAG_FORK 0x04 /* copy on fork */ #endif /* _KERNEL */ #if defined(_KERNEL) || defined(_WANT_FILE)