Index: sys/kern/init_main.c =================================================================== RCS file: /home/ncvs/src/sys/kern/init_main.c,v retrieving revision 1.238 diff -u -r1.238 init_main.c --- sys/kern/init_main.c 2 Oct 2003 03:57:59 -0000 1.238 +++ sys/kern/init_main.c 3 Dec 2003 17:08:08 -0000 @@ -415,6 +415,8 @@ fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; fdp->fd_fd.fd_nfiles = NDFILE; + fdp->fd_fd.fd_himap = fdp->fd_dhimap; + fdp->fd_fd.fd_lomap = fdp->fd_dlomap; /* Create the limits structures. */ p->p_limit = &limit0; Index: sys/kern/kern_descrip.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.215 diff -u -r1.215 kern_descrip.c --- sys/kern/kern_descrip.c 19 Oct 2003 20:41:06 -0000 1.215 +++ sys/kern/kern_descrip.c 17 Dec 2003 08:54:19 -0000 @@ -96,6 +96,8 @@ static int do_dup(struct thread *td, enum dup_type type, int old, int new, register_t *retval); +static int find_next_zero(uint32_t *, int, u_int); +static int fd_find_last_set(struct filedesc *, int); /* * Descriptor management. @@ -105,6 +107,104 @@ struct sx filelist_lock; /* sx to protect filelist */ struct mtx sigio_lock; /* mtx to protect pointers to sigio */ +static int +find_next_zero(uint32_t *bitmap, int want, u_int bits) +{ + int i, off, maxoff; + uint32_t sub; + + if (want > bits) + return (-1); + + off = want >> NDENTRYSHIFT; + i = want & NDENTRYMASK; + if (i) { + sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i)); + if (sub != ~0) + goto found; + off++; + } + + maxoff = NDLOSLOTS(bits); + while (off < maxoff) { + if ((sub = bitmap[off]) != ~0) + goto found; + off++; + } + + return (-1); + +found: + return ((off << NDENTRYSHIFT) + ffs(~sub) - 1); +} + +static int +fd_find_last_set(struct filedesc *fdp, int last) +{ + int off, i; + struct file **ofiles = fdp->fd_ofiles; + uint32_t *bitmap = fdp->fd_lomap; + + off = (last - 1) >> NDENTRYSHIFT; + + while (!bitmap[off] && off >= 0) + off--; + + if (off < 0) + return (0); + + i = ((off + 1) << NDENTRYSHIFT) - 1; + if (i >= last) + i = last - 1; + + while (i > 0 && ofiles[i] == NULL) + i--; + + return (i); +} + +/* + * Mark a file descriptor as used. + */ +void +fdused(struct filedesc *fdp, int fd) +{ + unsigned int off = fd >> NDENTRYSHIFT; + + FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); + KASSERT((fdp->fd_lomap[off] & NDBIT(fd)) == 0, + ("%s(): fd already used", __func__)); + fdp->fd_lomap[off] |= NDBIT(fd); + if (fdp->fd_lomap[off] == ~0) + fdp->fd_himap[off >> NDENTRYSHIFT] |= NDBIT(off); + if (fd > fdp->fd_lastfile) + fdp->fd_lastfile = fd; +} + +/* + * Mark a file descriptor as unused. + */ +void +fdunused(struct filedesc *fdp, int fd) +{ + unsigned int off = fd >> NDENTRYSHIFT; + + FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); + KASSERT((fdp->fd_lomap[off] & NDBIT(fd)) != 0, + ("%s(): fd is already unused", __func__)); + KASSERT(fdp->fd_ofiles[fd] == NULL, + ("%s(): fd is still in use", __func__)); + if (fd < fdp->fd_freefile) + fdp->fd_freefile = fd; + if (fdp->fd_lomap[off] == ~0) + fdp->fd_himap[off >> NDENTRYSHIFT] &= ~NDBIT(off); + fdp->fd_lomap[off] &= ~NDBIT(fd); + KASSERT(fd <= fdp->fd_lastfile, + ("%s(): fd_lastfile inconsistent", __func__)); + if (fd == fdp->fd_lastfile) + fdp->fd_lastfile = fd_find_last_set(fdp, fd); +} + /* * System calls on descriptors. */ @@ -125,7 +225,7 @@ struct proc *p = td->td_proc; mtx_lock(&Giant); - td->td_retval[0] = + td->td_retval[0] = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); mtx_unlock(&Giant); return (0); @@ -505,13 +605,9 @@ * avoid this case. */ if (fdp->fd_ofiles[old] != fp) { - if (fdp->fd_ofiles[new] == NULL) { - if (new < fdp->fd_freefile) - fdp->fd_freefile = new; - while (fdp->fd_lastfile > 0 && - fdp->fd_ofiles[fdp->fd_lastfile] == NULL) - fdp->fd_lastfile--; - } + /* we've allocated a descriptor which we won't use */ + if (fdp->fd_ofiles[new] == NULL) + fdunused(fdp, new); FILEDESC_UNLOCK(fdp); fdrop(fp, td); return (EBADF); @@ -531,8 +627,9 @@ */ fdp->fd_holdleaderscount++; holdleaders = 1; - } else + } else { holdleaders = 0; + } KASSERT(delfp == NULL || type == DUP_FIXED, ("dup() picked an open file")); #if 0 @@ -544,9 +641,7 @@ * Duplicate the source descriptor, update lastfile */ fdp->fd_ofiles[new] = fp; - fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; - if (new > fdp->fd_lastfile) - fdp->fd_lastfile = new; + fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; FILEDESC_UNLOCK(fdp); *retval = new; @@ -749,7 +844,7 @@ funsetown(sigiop); if (pgid > 0) { PROC_LOCK(proc); - /* + /* * Since funsetownlst() is called without the proctree * locked, we need to check for P_WEXIT. * XXX: is ESRCH correct? @@ -801,7 +896,7 @@ */ #ifndef _SYS_SYSPROTO_H_ struct close_args { - int fd; + int fd; }; #endif /* @@ -836,6 +931,7 @@ #endif fdp->fd_ofiles[fd] = NULL; fdp->fd_ofileflags[fd] = 0; + fdunused(fdp, fd); if (td->td_proc->p_fdtol != NULL) { /* * Ask fdfree() to sleep to ensure that all relevant @@ -849,10 +945,6 @@ * we now hold the fp reference that used to be owned by the descriptor * array. */ - while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) - fdp->fd_lastfile--; - if (fd < fdp->fd_freefile) - fdp->fd_freefile = fd; if (fd < fdp->fd_knlistsize) { FILEDESC_UNLOCK(fdp); knote_fdclose(td, fd); @@ -1052,9 +1144,11 @@ struct proc *p = td->td_proc; struct filedesc *fdp = td->td_proc->p_fd; int i; - int lim, last, nfiles; + int lim, last, nfiles, oldnfiles; struct file **newofile, **oldofile; char *newofileflags; + uint32_t *newhimap, *newlomap, *oldhimap, *oldlomap; + u_int off, new; FILEDESC_LOCK_ASSERT(fdp, MA_OWNED); @@ -1066,12 +1160,28 @@ lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); for (;;) { last = min(fdp->fd_nfiles, lim); +again: i = max(want, fdp->fd_freefile); - for (; i < last; i++) { - if (fdp->fd_ofiles[i] == NULL) { - fdp->fd_ofileflags[i] = 0; - if (i > fdp->fd_lastfile) - fdp->fd_lastfile = i; + off = i >> NDENTRYSHIFT; + new = find_next_zero(fdp->fd_himap, off, + (last + NDENTRIES - 1) >> NDENTRYSHIFT); + if (new != -1) { + i = find_next_zero(&fdp->fd_lomap[new], + new > off ? 0 : i & NDENTRYMASK, NDENTRIES); + if (i == -1) { + /* + * free file descriptor in this block was + * below want, try again with higher want. + */ + want = (new + 1) << NDENTRYSHIFT; + goto again; + } + i += (new << NDENTRYSHIFT); + if (i < last) { + KASSERT(fdp->fd_ofiles[i] == NULL, + ("free descriptor isn't")); + fdp->fd_ofileflags[i] = 0; /* XXX needed? */ + fdused(fdp, i); if (want <= fdp->fd_freefile) fdp->fd_freefile = i; *result = i; @@ -1082,7 +1192,7 @@ /* * No space in current array. Expand? */ - if (i >= lim) + if (fdp->fd_nfiles >= lim) return (EMFILE); if (fdp->fd_nfiles < NDEXTENT) nfiles = NDEXTENT; @@ -1090,8 +1200,17 @@ nfiles = 2 * fdp->fd_nfiles; while (nfiles < want) nfiles <<= 1; + oldnfiles = fdp->fd_nfiles; FILEDESC_UNLOCK(fdp); newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK); + if (NDHISLOTS(nfiles) > NDHISLOTS(oldnfiles)) { + newhimap = malloc(NDHISLOTS(nfiles) * NDSLOTSIZE, + M_FILEDESC, M_WAITOK); + newlomap = malloc(NDLOSLOTS(nfiles) * NDSLOTSIZE, + M_FILEDESC, M_WAITOK); + } else { + newhimap = newlomap = NULL; + } /* * Deal with file-table extend race that might have @@ -1101,6 +1220,10 @@ if (fdp->fd_nfiles >= nfiles) { FILEDESC_UNLOCK(fdp); free(newofile, M_FILEDESC); + if (newhimap != NULL) + free(newhimap, M_FILEDESC); + if (newlomap != NULL) + free(newlomap, M_FILEDESC); FILEDESC_LOCK(fdp); continue; } @@ -1122,11 +1245,33 @@ oldofile = NULL; fdp->fd_ofiles = newofile; fdp->fd_ofileflags = newofileflags; + oldlomap = oldhimap = NULL; + if (NDHISLOTS(nfiles) > NDHISLOTS(oldnfiles)) { + memcpy(newhimap, fdp->fd_himap, + (i = NDHISLOTS(oldnfiles) * NDSLOTSIZE)); + memset((char *)newhimap + i, 0, + NDHISLOTS(nfiles) * NDSLOTSIZE - i); + memcpy(newlomap, fdp->fd_lomap, + (i = NDLOSLOTS(oldnfiles) * NDSLOTSIZE)); + memset((char *)newlomap + i, 0, + NDLOSLOTS(nfiles) * NDSLOTSIZE - i); + if (NDHISLOTS(oldnfiles) > NDHISLOTS(NDFILE)) { + oldhimap = fdp->fd_himap; + oldlomap = fdp->fd_lomap; + } + fdp->fd_himap = newhimap; + fdp->fd_lomap = newlomap; + } fdp->fd_nfiles = nfiles; fdexpand++; - if (oldofile != NULL) { + if (oldofile != NULL || oldlomap != NULL || oldhimap != NULL) { FILEDESC_UNLOCK(fdp); - free(oldofile, M_FILEDESC); + if (oldofile != NULL) + free(oldofile, M_FILEDESC); + if (oldlomap != NULL) + free(oldlomap, M_FILEDESC); + if (oldhimap != NULL) + free(oldhimap, M_FILEDESC); FILEDESC_LOCK(fdp); } } @@ -1188,7 +1333,7 @@ if (ppsratecheck(&lastfail, &curfail, 1)) { printf("kern.maxfiles limit exceeded by uid %i, please see tuning(7).\n", td->td_ucred->cr_ruid); - } + } sx_xunlock(&filelist_lock); uma_zfree(file_zone, fp); return (ENFILE); @@ -1276,6 +1421,8 @@ newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; newfdp->fd_fd.fd_nfiles = NDFILE; newfdp->fd_fd.fd_knlistsize = -1; + newfdp->fd_fd.fd_himap = newfdp->fd_dhimap; + newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap; return (&newfdp->fd_fd); } @@ -1340,6 +1487,10 @@ newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; newfdp->fd_ofileflags = ((struct filedesc0 *) newfdp)->fd_dfileflags; + newfdp->fd_himap = + ((struct filedesc0 *) newfdp)->fd_dhimap; + newfdp->fd_lomap = + ((struct filedesc0 *) newfdp)->fd_dlomap; i = NDFILE; } else { /* @@ -1354,6 +1505,17 @@ FILEDESC_UNLOCK(fdp); MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, M_FILEDESC, M_WAITOK); + if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) { + newfdp->fd_himap = + ((struct filedesc0 *) newfdp)->fd_dhimap; + newfdp->fd_lomap = + ((struct filedesc0 *) newfdp)->fd_dlomap; + } else { + newfdp->fd_himap = malloc(NDHISLOTS(i) * NDSLOTSIZE, + M_FILEDESC, M_WAITOK); + newfdp->fd_lomap = malloc(NDLOSLOTS(i) * NDSLOTSIZE, + M_FILEDESC, M_WAITOK); + } FILEDESC_LOCK(fdp); newfdp->fd_lastfile = fdp->fd_lastfile; newfdp->fd_nfiles = fdp->fd_nfiles; @@ -1377,6 +1539,10 @@ newfdp->fd_nfiles = i; bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); + if (i < NDENTRIES * NDENTRIES) + i = NDENTRIES * NDENTRIES; /* size of inlined bitmaps */ + memcpy(newfdp->fd_himap, fdp->fd_himap, NDHISLOTS(i) * NDSLOTSIZE); + memcpy(newfdp->fd_lomap, fdp->fd_lomap, NDLOSLOTS(i) * NDSLOTSIZE); /* * kq descriptors cannot be copied. @@ -1385,12 +1551,9 @@ fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile]; for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) { if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) { + fdunused(newfdp, i); *fpp = NULL; - if (i < newfdp->fd_freefile) - newfdp->fd_freefile = i; } - if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0) - newfdp->fd_lastfile--; } newfdp->fd_knlist = NULL; newfdp->fd_knlistsize = -1; @@ -1480,7 +1643,7 @@ goto retry; } if (fdtol->fdl_holdcount > 0) { - /* + /* * Ensure that fdtol->fdl_leader * remains valid in closef(). */ @@ -1526,6 +1689,10 @@ if (fdp->fd_nfiles > NDFILE) FREE(fdp->fd_ofiles, M_FILEDESC); + if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) { + free(fdp->fd_himap, M_FILEDESC); + free(fdp->fd_lomap, M_FILEDESC); + } if (fdp->fd_cdir) vrele(fdp->fd_cdir); if (fdp->fd_rdir) @@ -1603,15 +1770,12 @@ fp = fdp->fd_ofiles[i]; fdp->fd_ofiles[i] = NULL; fdp->fd_ofileflags[i] = 0; - if (i < fdp->fd_freefile) - fdp->fd_freefile = i; + fdunused(fdp, i); FILEDESC_UNLOCK(fdp); (void) closef(fp, td); FILEDESC_LOCK(fdp); } } - while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) - fdp->fd_lastfile--; FILEDESC_UNLOCK(fdp); } @@ -1657,15 +1821,12 @@ fp = fdp->fd_ofiles[i]; fdp->fd_ofiles[i] = NULL; fdp->fd_ofileflags[i] = 0; - if (i < fdp->fd_freefile) - fdp->fd_freefile = i; + fdunused(fdp, i); FILEDESC_UNLOCK(fdp); (void) closef(fp, td); FILEDESC_LOCK(fdp); } } - while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) - fdp->fd_lastfile--; FILEDESC_UNLOCK(fdp); } @@ -1714,6 +1875,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[fd] == fp) { fdp->fd_ofiles[fd] = NULL; + fdunused(fdp, fd); extraref = 1; } FILEDESC_UNLOCK(fdp); @@ -2182,10 +2344,9 @@ #endif fdp->fd_ofiles[indx] = wfp; fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; + fdused(fdp, indx); fhold_locked(wfp); FILE_UNLOCK(wfp); - if (indx > fdp->fd_lastfile) - fdp->fd_lastfile = indx; if (fp != NULL) FILE_LOCK(fp); FILEDESC_UNLOCK(fdp); @@ -2210,21 +2371,8 @@ fdp->fd_ofiles[dfd] = NULL; fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; fdp->fd_ofileflags[dfd] = 0; - - /* - * Complete the clean up of the filedesc structure by - * recomputing the various hints. - */ - if (indx > fdp->fd_lastfile) { - fdp->fd_lastfile = indx; - } else { - while (fdp->fd_lastfile > 0 && - fdp->fd_ofiles[fdp->fd_lastfile] == NULL) { - fdp->fd_lastfile--; - } - if (dfd < fdp->fd_freefile) - fdp->fd_freefile = dfd; - } + fdunused(fdp, dfd); + fdused(fdp, indx); if (fp != NULL) FILE_LOCK(fp); FILEDESC_UNLOCK(fdp); @@ -2251,7 +2399,7 @@ struct proc *leader) { struct filedesc_to_leader *fdtol; - + MALLOC(fdtol, struct filedesc_to_leader *, sizeof(struct filedesc_to_leader), M_FILEDESC_TO_LEADER, @@ -2271,7 +2419,7 @@ fdtol->fdl_next = fdtol; fdtol->fdl_prev = fdtol; } - return fdtol; + return (fdtol); } /* @@ -2355,13 +2503,13 @@ SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD, 0, 0, sysctl_kern_file, "S,xfile", "Entire file table"); -SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW, +SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW, &maxfilesperproc, 0, "Maximum files allowed open per process"); -SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, +SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, &maxfiles, 0, "Maximum number of files"); -SYSCTL_INT(_kern, OID_AUTO, openfiles, CTLFLAG_RD, +SYSCTL_INT(_kern, OID_AUTO, openfiles, CTLFLAG_RD, &nfiles, 0, "System-wide number of open files"); static void Index: sys/kern/sys_pipe.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_pipe.c,v retrieving revision 1.158 diff -u -r1.158 sys_pipe.c --- sys/kern/sys_pipe.c 9 Nov 2003 09:17:24 -0000 1.158 +++ sys/kern/sys_pipe.c 9 Dec 2003 20:51:35 -0000 @@ -258,10 +258,12 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[td->td_retval[0]] == rf) { fdp->fd_ofiles[td->td_retval[0]] = NULL; + fdunused(fdp, td->td_retval[0]); FILEDESC_UNLOCK(fdp); fdrop(rf, td); - } else + } else { FILEDESC_UNLOCK(fdp); + } fdrop(rf, td); /* rpipe has been closed by fdrop(). */ pipeclose(wpipe); Index: sys/kern/uipc_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.159 diff -u -r1.159 uipc_syscalls.c --- sys/kern/uipc_syscalls.c 1 Dec 2003 22:12:50 -0000 1.159 +++ sys/kern/uipc_syscalls.c 9 Dec 2003 20:49:21 -0000 @@ -124,6 +124,7 @@ if (error) { if (fdp->fd_ofiles[fd] == fp) { fdp->fd_ofiles[fd] = NULL; + fdunused(fdp, fd); FILEDESC_UNLOCK(fdp); fdrop(fp, td); } else @@ -389,6 +390,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[fd] == nfp) { fdp->fd_ofiles[fd] = NULL; + fdunused(fdp, fd); FILEDESC_UNLOCK(fdp); fdrop(nfp, td); } else { @@ -454,7 +456,7 @@ error = getsockaddr(&sa, uap->name, uap->namelen); if (error) - return error; + return (error); return (kern_connect(td, uap->s, sa)); } @@ -583,6 +585,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[sv[1]] == fp2) { fdp->fd_ofiles[sv[1]] = NULL; + fdunused(fdp, sv[1]); FILEDESC_UNLOCK(fdp); fdrop(fp2, td); } else @@ -592,6 +595,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[sv[0]] == fp1) { fdp->fd_ofiles[sv[0]] = NULL; + fdunused(fdp, sv[0]); FILEDESC_UNLOCK(fdp); fdrop(fp1, td); } else @@ -1601,7 +1605,7 @@ int error; if (len > SOCK_MAXADDRLEN) - return ENAMETOOLONG; + return (ENAMETOOLONG); MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK); error = copyin(uaddr, sa, len); if (error) { @@ -1614,7 +1618,7 @@ sa->sa_len = len; *namp = sa; } - return error; + return (error); } /* Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.333 diff -u -r1.333 vfs_syscalls.c --- sys/kern/vfs_syscalls.c 12 Nov 2003 08:01:39 -0000 1.333 +++ sys/kern/vfs_syscalls.c 9 Dec 2003 20:51:27 -0000 @@ -998,6 +998,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[indx] == fp) { fdp->fd_ofiles[indx] = NULL; + fdunused(fdp, indx); FILEDESC_UNLOCK(fdp); fdrop(fp, td); } else @@ -1030,7 +1031,7 @@ vn_close(vp, flags & FMASK, fp->f_cred, td); fdrop(fp, td); td->td_retval[0] = indx; - return 0; + return (0); } fp->f_vnode = vp; fp->f_data = vp; @@ -1090,6 +1091,7 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[indx] == fp) { fdp->fd_ofiles[indx] = NULL; + fdunused(fdp, indx); FILEDESC_UNLOCK(fdp); fdrop(fp, td); } else @@ -2313,7 +2315,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = setfflags(td, nd.ni_vp, uap->flags); vrele(nd.ni_vp); - return error; + return (error); } /* @@ -2336,7 +2338,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = setfflags(td, nd.ni_vp, uap->flags); vrele(nd.ni_vp); - return error; + return (error); } /* @@ -2393,7 +2395,7 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); - return error; + return (error); } /* @@ -2430,7 +2432,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = setfmode(td, nd.ni_vp, mode); vrele(nd.ni_vp); - return error; + return (error); } /* @@ -2460,7 +2462,7 @@ NDFREE(&nd, NDF_ONLY_PNBUF); error = setfmode(td, nd.ni_vp, uap->mode); vrele(nd.ni_vp); - return error; + return (error); } /* @@ -2520,7 +2522,7 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); - return error; + return (error); } /* @@ -2662,7 +2664,7 @@ TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); } - return 0; + return (0); } /* @@ -2705,7 +2707,7 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); - return error; + return (error); } /* @@ -3978,10 +3980,12 @@ FILEDESC_LOCK(fdp); if (fdp->fd_ofiles[indx] == fp) { fdp->fd_ofiles[indx] = NULL; + fdunused(fdp, indx); FILEDESC_UNLOCK(fdp); fdrop(fp, td); - } else + } else { FILEDESC_UNLOCK(fdp); + } /* * release our private reference */ Index: sys/sys/filedesc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/filedesc.h,v retrieving revision 1.52 diff -u -r1.52 filedesc.h --- sys/sys/filedesc.h 11 Nov 2003 22:07:29 -0000 1.52 +++ sys/sys/filedesc.h 9 Dec 2003 20:51:06 -0000 @@ -57,6 +57,13 @@ */ #define NDFILE 20 #define NDEXTENT 50 /* 250 bytes in 256-byte alloc. */ +#define NDENTRYSHIFT 5 /* bits per entry */ +#define NDENTRIES (1 << NDENTRYSHIFT) +#define NDENTRYMASK (NDENTRIES - 1) +#define NDSLOTSIZE sizeof(uint32_t) +#define NDBIT(x) (1 << ((x) & NDENTRYMASK)) +#define NDLOSLOTS(x) (((x) + NDENTRIES - 1) >> NDENTRYSHIFT) +#define NDHISLOTS(x) ((NDLOSLOTS(x) + NDENTRIES - 1) >> NDENTRYSHIFT) struct filedesc { struct file **fd_ofiles; /* file structures for open files */ @@ -65,6 +72,8 @@ struct vnode *fd_rdir; /* root directory */ struct vnode *fd_jdir; /* jail root directory */ int fd_nfiles; /* number of open files allocated */ + uint32_t *fd_himap; /* each bit points to 32 fds */ + uint32_t *fd_lomap; /* 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 */ @@ -91,6 +100,12 @@ */ struct file *fd_dfiles[NDFILE]; char fd_dfileflags[NDFILE]; + /* + * These arrays are used when the number of open files is + * <= 1024, and are then pointed to by the pointers above. + */ + uint32_t fd_dhimap[NDENTRIES >> NDENTRYSHIFT]; + uint32_t fd_dlomap[NDENTRIES]; }; @@ -143,6 +158,8 @@ int dupfdopen(struct thread *td, struct filedesc *fdp, int indx, int dfd, int mode, int error); int falloc(struct thread *p, struct file **resultfp, int *resultfd); +void fdused(struct filedesc *fdp, int fd); +void fdunused(struct filedesc *fdp, int fd); int fdalloc(struct thread *p, int want, int *result); int fdavail(struct thread *td, int n); void fdcloseexec(struct thread *td);