From owner-svn-src-head@freebsd.org Wed Jul 15 10:24:06 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 04528361EEE; Wed, 15 Jul 2020 10:24:06 +0000 (UTC) (envelope-from mjg@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4B6D516Z71z483v; Wed, 15 Jul 2020 10:24:05 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id C1CBE15D0E; Wed, 15 Jul 2020 10:24:05 +0000 (UTC) (envelope-from mjg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 06FAO5Uu007874; Wed, 15 Jul 2020 10:24:05 GMT (envelope-from mjg@FreeBSD.org) Received: (from mjg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06FAO4YC007868; Wed, 15 Jul 2020 10:24:04 GMT (envelope-from mjg@FreeBSD.org) Message-Id: <202007151024.06FAO4YC007868@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mjg set sender to mjg@FreeBSD.org using -f From: Mateusz Guzik Date: Wed, 15 Jul 2020 10:24:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363214 - in head/sys: kern sys X-SVN-Group: head X-SVN-Commit-Author: mjg X-SVN-Commit-Paths: in head/sys: kern sys X-SVN-Commit-Revision: 363214 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jul 2020 10:24:06 -0000 Author: mjg Date: Wed Jul 15 10:24:04 2020 New Revision: 363214 URL: https://svnweb.freebsd.org/changeset/base/363214 Log: fd: remove fd_lastfile It keeps recalculated way more often than it is needed. Provide a routine (fdlastfile) to get it if necessary. Consumers may be better off with a bitmap iterator instead. Modified: head/sys/kern/init_main.c head/sys/kern/kern_descrip.c head/sys/kern/kern_exec.c head/sys/kern/kern_fork.c head/sys/kern/sys_generic.c head/sys/sys/filedesc.h Modified: head/sys/kern/init_main.c ============================================================================== --- head/sys/kern/init_main.c Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/kern/init_main.c Wed Jul 15 10:24:04 2020 (r363214) @@ -558,7 +558,7 @@ proc0_init(void *dummy __unused) siginit(&proc0); /* Create the file descriptor table. */ - p->p_fd = fdinit(NULL, false); + p->p_fd = fdinit(NULL, false, NULL); p->p_fdtol = NULL; /* Create the limits structures. */ Modified: head/sys/kern/kern_descrip.c ============================================================================== --- head/sys/kern/kern_descrip.c Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/kern/kern_descrip.c Wed Jul 15 10:24:04 2020 (r363214) @@ -108,7 +108,6 @@ static __read_mostly smr_t pwd_smr; static int closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td, int holdleaders); static int fd_first_free(struct filedesc *fdp, int low, int size); -static int fd_last_used(struct filedesc *fdp, int size); static void fdgrowtable(struct filedesc *fdp, int nfd); static void fdgrowtable_exp(struct filedesc *fdp, int nfd); static void fdunused(struct filedesc *fdp, int fd); @@ -213,29 +212,32 @@ fd_first_free(struct filedesc *fdp, int low, int size) } /* - * Find the highest non-zero bit in the given bitmap, starting at 0 and - * not exceeding size - 1. Return -1 if not found. + * Find the last used fd. + * + * Call this variant if fdp can't be modified by anyone else (e.g, during exec). + * Otherwise use fdlastfile. */ -static int -fd_last_used(struct filedesc *fdp, int size) +int +fdlastfile_single(struct filedesc *fdp) { NDSLOTTYPE *map = fdp->fd_map; - NDSLOTTYPE mask; int off, minoff; - off = NDSLOT(size); - if (size % NDENTRIES) { - mask = ~(~(NDSLOTTYPE)0 << (size % NDENTRIES)); - if ((mask &= map[off]) != 0) - return (off * NDENTRIES + flsl(mask) - 1); - --off; - } + off = NDSLOT(fdp->fd_nfiles - 1); for (minoff = NDSLOT(0); off >= minoff; --off) if (map[off] != 0) return (off * NDENTRIES + flsl(map[off]) - 1); return (-1); } +int +fdlastfile(struct filedesc *fdp) +{ + + FILEDESC_LOCK_ASSERT(fdp); + return (fdlastfile_single(fdp)); +} + static int fdisused(struct filedesc *fdp, int fd) { @@ -265,8 +267,6 @@ fdused(struct filedesc *fdp, int fd) FILEDESC_XLOCK_ASSERT(fdp); fdused_init(fdp, fd); - if (fd > fdp->fd_lastfile) - fdp->fd_lastfile = fd; if (fd == fdp->fd_freefile) fdp->fd_freefile++; } @@ -287,8 +287,6 @@ fdunused(struct filedesc *fdp, int fd) fdp->fd_map[NDSLOT(fd)] &= ~NDBIT(fd); if (fd < fdp->fd_freefile) fdp->fd_freefile = fd; - if (fd == fdp->fd_lastfile) - fdp->fd_lastfile = fd_last_used(fdp, fd); } /* @@ -1317,7 +1315,7 @@ int kern_close_range(struct thread *td, u_int lowfd, u_int highfd) { struct filedesc *fdp; - int fd, ret; + int fd, ret, lastfile; ret = 0; fdp = td->td_proc->p_fd; @@ -1335,14 +1333,15 @@ kern_close_range(struct thread *td, u_int lowfd, u_int } /* - * If fdp->fd_lastfile == -1, we're dealing with either a fresh file + * If lastfile == -1, we're dealing with either a fresh file * table or one in which every fd has been closed. Just return * successful; there's nothing left to do. */ - if (fdp->fd_lastfile == -1) + lastfile = fdlastfile(fdp); + if (lastfile == -1) goto out; - /* Clamped to [lowfd, fd_lastfile] */ - highfd = MIN(highfd, fdp->fd_lastfile); + /* Clamped to [lowfd, lastfile] */ + highfd = MIN(highfd, lastfile); for (fd = lowfd; fd <= highfd; fd++) { if (fdp->fd_ofiles[fd].fde_file != NULL) { FILEDESC_SUNLOCK(fdp); @@ -1741,14 +1740,6 @@ fdgrowtable(struct filedesc *fdp, int nfd) int nnfiles, onfiles; NDSLOTTYPE *nmap, *omap; - /* - * If lastfile is -1 this struct filedesc was just allocated and we are - * growing it to accommodate for the one we are going to copy from. There - * is no need to have a lock on this one as it's not visible to anyone. - */ - if (fdp->fd_lastfile != -1) - FILEDESC_XLOCK_ASSERT(fdp); - KASSERT(fdp->fd_nfiles > 0, ("zero-length file table")); /* save old values */ @@ -2033,12 +2024,17 @@ finstall(struct thread *td, struct file *fp, int *fd, * If fdp is not NULL, return with it shared locked. */ struct filedesc * -fdinit(struct filedesc *fdp, bool prepfiles) +fdinit(struct filedesc *fdp, bool prepfiles, int *lastfile) { struct filedesc0 *newfdp0; struct filedesc *newfdp; struct pwd *newpwd; + if (prepfiles) + MPASS(lastfile != NULL); + else + MPASS(lastfile == NULL); + newfdp0 = uma_zalloc(filedesc0_zone, M_WAITOK | M_ZERO); newfdp = &newfdp0->fd_fd; @@ -2048,7 +2044,6 @@ fdinit(struct filedesc *fdp, bool prepfiles) refcount_init(&newfdp->fd_holdcnt, 1); newfdp->fd_cmask = CMASK; newfdp->fd_map = newfdp0->fd_dmap; - newfdp->fd_lastfile = -1; newfdp->fd_files = (struct fdescenttbl *)&newfdp0->fd_dfiles; newfdp->fd_files->fdt_nfiles = NDFILE; @@ -2058,23 +2053,23 @@ fdinit(struct filedesc *fdp, bool prepfiles) return (newfdp); } - if (prepfiles && fdp->fd_lastfile >= newfdp->fd_nfiles) - fdgrowtable(newfdp, fdp->fd_lastfile + 1); - FILEDESC_SLOCK(fdp); newpwd = pwd_hold_filedesc(fdp); smr_serialized_store(&newfdp->fd_pwd, newpwd, true); - if (!prepfiles) { FILEDESC_SUNLOCK(fdp); - } else { - while (fdp->fd_lastfile >= newfdp->fd_nfiles) { - FILEDESC_SUNLOCK(fdp); - fdgrowtable(newfdp, fdp->fd_lastfile + 1); - FILEDESC_SLOCK(fdp); - } + return (newfdp); } + for (;;) { + *lastfile = fdlastfile(fdp); + if (*lastfile < newfdp->fd_nfiles) + break; + FILEDESC_SUNLOCK(fdp); + fdgrowtable(newfdp, *lastfile + 1); + FILEDESC_SLOCK(fdp); + } + return (newfdp); } @@ -2148,14 +2143,14 @@ fdcopy(struct filedesc *fdp) { struct filedesc *newfdp; struct filedescent *nfde, *ofde; - int i; + int i, lastfile; MPASS(fdp != NULL); - newfdp = fdinit(fdp, true); + newfdp = fdinit(fdp, true, &lastfile); /* copy all passable descriptors (i.e. not kqueue) */ newfdp->fd_freefile = -1; - for (i = 0; i <= fdp->fd_lastfile; ++i) { + for (i = 0; i <= lastfile; ++i) { ofde = &fdp->fd_ofiles[i]; if (ofde->fde_file == NULL || (ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 || @@ -2168,7 +2163,6 @@ fdcopy(struct filedesc *fdp) *nfde = *ofde; filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true); fdused_init(newfdp, i); - newfdp->fd_lastfile = i; } if (newfdp->fd_freefile == -1) newfdp->fd_freefile = i; @@ -2190,12 +2184,12 @@ fdcopy_remapped(struct filedesc *fdp, const int *fds, { struct filedesc *newfdp; struct filedescent *nfde, *ofde; - int error, i; + int error, i, lastfile; MPASS(fdp != NULL); - newfdp = fdinit(fdp, true); - if (nfds > fdp->fd_lastfile + 1) { + newfdp = fdinit(fdp, true, &lastfile); + if (nfds > lastfile + 1) { /* New table cannot be larger than the old one. */ error = E2BIG; goto bad; @@ -2203,7 +2197,7 @@ fdcopy_remapped(struct filedesc *fdp, const int *fds, /* Copy all passable descriptors (i.e. not kqueue). */ newfdp->fd_freefile = nfds; for (i = 0; i < nfds; ++i) { - if (fds[i] < 0 || fds[i] > fdp->fd_lastfile) { + if (fds[i] < 0 || fds[i] > lastfile) { /* File descriptor out of bounds. */ error = EBADF; goto bad; @@ -2227,7 +2221,6 @@ fdcopy_remapped(struct filedesc *fdp, const int *fds, *nfde = *ofde; filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true); fdused_init(newfdp, i); - newfdp->fd_lastfile = i; } newfdp->fd_cmask = fdp->fd_cmask; FILEDESC_SUNLOCK(fdp); @@ -2252,7 +2245,7 @@ fdclearlocks(struct thread *td) struct file *fp; struct proc *p; struct vnode *vp; - int i; + int i, lastfile; p = td->td_proc; fdp = p->p_fd; @@ -2265,7 +2258,8 @@ fdclearlocks(struct thread *td) fdtol->fdl_refcount)); if (fdtol->fdl_refcount == 1 && (p->p_leader->p_flag & P_ADVLOCK) != 0) { - for (i = 0; i <= fdp->fd_lastfile; i++) { + lastfile = fdlastfile(fdp); + for (i = 0; i <= lastfile; i++) { fp = fdp->fd_ofiles[i].fde_file; if (fp == NULL || fp->f_type != DTYPE_VNODE || !fhold(fp)) @@ -2330,9 +2324,10 @@ fdescfree_fds(struct thread *td, struct filedesc *fdp, struct freetable *ft, *tft; struct filedescent *fde; struct file *fp; - int i; + int i, lastfile; - for (i = 0; i <= fdp->fd_lastfile; i++) { + lastfile = fdlastfile_single(fdp); + for (i = 0; i <= lastfile; i++) { fde = &fdp->fd_ofiles[i]; fp = fde->fde_file; if (fp != NULL) { @@ -2480,11 +2475,12 @@ fdcloseexec(struct thread *td) struct filedesc *fdp; struct filedescent *fde; struct file *fp; - int i; + int i, lastfile; fdp = td->td_proc->p_fd; KASSERT(fdp->fd_refcnt == 1, ("the fdtable should not be shared")); - for (i = 0; i <= fdp->fd_lastfile; i++) { + lastfile = fdlastfile_single(fdp); + for (i = 0; i <= lastfile; i++) { fde = &fdp->fd_ofiles[i]; fp = fde->fde_file; if (fp != NULL && (fp->f_type == DTYPE_MQUEUE || @@ -3289,11 +3285,12 @@ chroot_refuse_vdir_fds(struct filedesc *fdp) { struct vnode *vp; struct file *fp; - int fd; + int fd, lastfile; FILEDESC_LOCK_ASSERT(fdp); - for (fd = 0; fd <= fdp->fd_lastfile; fd++) { + lastfile = fdlastfile(fdp); + for (fd = 0; fd <= lastfile; fd++) { fp = fget_locked(fdp, fd); if (fp == NULL) continue; @@ -3610,8 +3607,9 @@ filedesc_to_leader_alloc(struct filedesc_to_leader *ol static int sysctl_kern_proc_nfds(SYSCTL_HANDLER_ARGS) { + NDSLOTTYPE *map; struct filedesc *fdp; - int i, count, slots; + int count, off, minoff; if (*(int *)arg1 != 0) return (EINVAL); @@ -3619,9 +3617,10 @@ sysctl_kern_proc_nfds(SYSCTL_HANDLER_ARGS) fdp = curproc->p_fd; count = 0; FILEDESC_SLOCK(fdp); - slots = NDSLOTS(fdp->fd_lastfile + 1); - for (i = 0; i < slots; i++) - count += bitcountl(fdp->fd_map[i]); + map = fdp->fd_map; + off = NDSLOT(fdp->fd_nfiles - 1); + for (minoff = NDSLOT(0); off >= minoff; --off) + count += bitcountl(map[off]); FILEDESC_SUNLOCK(fdp); return (SYSCTL_OUT(req, &count, sizeof(count))); @@ -3641,7 +3640,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) struct filedesc *fdp; struct file *fp; struct proc *p; - int error, n; + int error, n, lastfile; error = sysctl_wire_old_buffer(req, 0); if (error != 0) @@ -3660,8 +3659,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) if (fdp == NULL) continue; /* overestimates sparse tables. */ - if (fdp->fd_lastfile > 0) - n += fdp->fd_lastfile; + n += fdp->fd_nfiles; fddrop(fdp); } sx_sunlock(&allproc_lock); @@ -3688,7 +3686,8 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) if (fdp == NULL) continue; FILEDESC_SLOCK(fdp); - for (n = 0; fdp->fd_refcnt > 0 && n <= fdp->fd_lastfile; ++n) { + lastfile = fdlastfile(fdp); + for (n = 0; fdp->fd_refcnt > 0 && n <= lastfile; ++n) { if ((fp = fdp->fd_ofiles[n].fde_file) == NULL) continue; xf.xf_fd = n; @@ -3891,7 +3890,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *s struct export_fd_buf *efbuf; struct vnode *cttyvp, *textvp, *tracevp; struct pwd *pwd; - int error, i; + int error, i, lastfile; cap_rights_t rights; PROC_LOCK_ASSERT(p, MA_OWNED); @@ -3950,7 +3949,8 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *s } pwd_drop(pwd); } - for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { + lastfile = fdlastfile(fdp); + for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) { if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) continue; #ifdef CAPABILITIES @@ -4064,7 +4064,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) struct kinfo_file *kif; struct filedesc *fdp; struct pwd *pwd; - int error, i, *name; + int error, i, lastfile, *name; struct file *fp; struct proc *p; @@ -4092,7 +4092,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) okif, fdp, req); pwd_drop(pwd); } - for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) { + lastfile = fdlastfile(fdp); + for (i = 0; fdp->fd_refcnt > 0 && i <= lastfile; i++) { if ((fp = fdp->fd_ofiles[i].fde_file) == NULL) continue; export_file_to_kinfo(fp, i, NULL, kif, fdp, @@ -4283,7 +4284,7 @@ file_to_first_proc(struct file *fp) fdp = p->p_fd; if (fdp == NULL) continue; - for (n = 0; n <= fdp->fd_lastfile; n++) { + for (n = 0; n < fdp->fd_nfiles; n++) { if (fp == fdp->fd_ofiles[n].fde_file) return (p); } @@ -4337,7 +4338,7 @@ DB_SHOW_COMMAND(files, db_show_files) continue; if ((fdp = p->p_fd) == NULL) continue; - for (n = 0; n <= fdp->fd_lastfile; ++n) { + for (n = 0; n < fdp->fd_nfiles; ++n) { if ((fp = fdp->fd_ofiles[n].fde_file) == NULL) continue; db_print_file(fp, header); Modified: head/sys/kern/kern_exec.c ============================================================================== --- head/sys/kern/kern_exec.c Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/kern/kern_exec.c Wed Jul 15 10:24:04 2020 (r363214) @@ -1208,7 +1208,7 @@ exec_copyin_data_fds(struct thread *td, struct image_a memset(args, '\0', sizeof(*args)); ofdp = td->td_proc->p_fd; - if (datalen >= ARG_MAX || fdslen > ofdp->fd_lastfile + 1) + if (datalen >= ARG_MAX || fdslen >= ofdp->fd_nfiles) return (E2BIG); error = exec_alloc_args(args); if (error != 0) Modified: head/sys/kern/kern_fork.c ============================================================================== --- head/sys/kern/kern_fork.c Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/kern/kern_fork.c Wed Jul 15 10:24:04 2020 (r363214) @@ -332,7 +332,7 @@ fork_norfproc(struct thread *td, int flags) */ if (flags & RFCFDG) { struct filedesc *fdtmp; - fdtmp = fdinit(td->td_proc->p_fd, false); + fdtmp = fdinit(td->td_proc->p_fd, false, NULL); fdescfree(td); p1->p_fd = fdtmp; } @@ -403,7 +403,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct * Copy filedesc. */ if (fr->fr_flags & RFCFDG) { - fd = fdinit(p1->p_fd, false); + fd = fdinit(p1->p_fd, false, NULL); fdtol = NULL; } else if (fr->fr_flags & RFFDG) { fd = fdcopy(p1->p_fd); Modified: head/sys/kern/sys_generic.c ============================================================================== --- head/sys/kern/sys_generic.c Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/kern/sys_generic.c Wed Jul 15 10:24:04 2020 (r363214) @@ -960,7 +960,7 @@ sys_select(struct thread *td, struct select_args *uap) * * There are applications that rely on the behaviour. * - * nd is fd_lastfile + 1. + * nd is fd_nfiles. */ static int select_check_badfd(fd_set *fd_in, int nd, int ndu, int abi_nfdbits) @@ -1023,9 +1023,9 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, return (EINVAL); fdp = td->td_proc->p_fd; ndu = nd; - lf = fdp->fd_lastfile; - if (nd > lf + 1) - nd = lf + 1; + lf = fdp->fd_nfiles; + if (nd > lf) + nd = lf; error = select_check_badfd(fd_in, nd, ndu, abi_nfdbits); if (error != 0) @@ -1556,7 +1556,7 @@ pollscan(struct thread *td, struct pollfd *fds, u_int FILEDESC_SLOCK(fdp); for (i = 0; i < nfd; i++, fds++) { - if (fds->fd > fdp->fd_lastfile) { + if (fds->fd >= fdp->fd_nfiles) { fds->revents = POLLNVAL; n++; } else if (fds->fd < 0) { Modified: head/sys/sys/filedesc.h ============================================================================== --- head/sys/sys/filedesc.h Wed Jul 15 10:14:00 2020 (r363213) +++ head/sys/sys/filedesc.h Wed Jul 15 10:24:04 2020 (r363214) @@ -96,7 +96,6 @@ struct filedesc { struct fdescenttbl *fd_files; /* open files table */ smrpwd_t fd_pwd; /* directories */ NDSLOTTYPE *fd_map; /* bitmap of free fds */ - int fd_lastfile; /* high-water mark of fd_ofiles */ int fd_freefile; /* approx. next free file */ u_short fd_cmask; /* mask for file creation */ int fd_refcnt; /* thread reference count */ @@ -235,7 +234,9 @@ void fdinstall_remapped(struct thread *td, struct file void fdunshare(struct thread *td); void fdescfree(struct thread *td); void fdescfree_remapped(struct filedesc *fdp); -struct filedesc *fdinit(struct filedesc *fdp, bool prepfiles); +int fdlastfile(struct filedesc *fdp); +int fdlastfile_single(struct filedesc *fdp); +struct filedesc *fdinit(struct filedesc *fdp, bool prepfiles, int *lastfile); struct filedesc *fdshare(struct filedesc *fdp); struct filedesc_to_leader * filedesc_to_leader_alloc(struct filedesc_to_leader *old,