diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2018-04-26 06:28:44 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2018-04-26 06:28:44 +0000 |
commit | 3983ebaa8ac639491edf5f6d3e34a8513af8fbe3 (patch) | |
tree | 728fcde8bf445d6d306f34dcf7c7e9762c013262 /sys/kern/kern_descrip.c | |
parent | d6fc1c3b188130d310f25f5dd83f1afc0b23b367 (diff) |
Rewrite fdcopy() to avoid memcpy()s.
With and ok visa@
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 90 |
1 files changed, 38 insertions, 52 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 100d86f4c49..aea5be59539 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.152 2018/04/25 10:29:16 mpi Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.153 2018/04/26 06:28:43 mpi Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -1016,18 +1016,19 @@ struct filedesc * fdcopy(struct process *pr) { struct filedesc *newfdp, *fdp = pr->ps_fd; - struct file **fpp; int i; + newfdp = fdinit(); + fdplock(fdp); - newfdp = pool_get(&fdesc_pool, PR_WAITOK); - memcpy(newfdp, fdp, sizeof(struct filedesc)); - if (newfdp->fd_cdir) - vref(newfdp->fd_cdir); - if (newfdp->fd_rdir) - vref(newfdp->fd_rdir); - newfdp->fd_refcnt = 1; - rw_init(&newfdp->fd_lock, "fdlock"); + if (fdp->fd_cdir) { + vref(fdp->fd_cdir); + newfdp->fd_cdir = fdp->fd_cdir; + } + if (fdp->fd_rdir) { + vref(fdp->fd_rdir); + newfdp->fd_rdir = fdp->fd_rdir; + } /* * If the number of open files fits in the internal arrays @@ -1035,45 +1036,34 @@ fdcopy(struct process *pr) * additional memory for the number of descriptors currently * in use. */ - if (newfdp->fd_lastfile < NDFILE) { - newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; - newfdp->fd_ofileflags = - ((struct filedesc0 *) newfdp)->fd_dfileflags; - i = NDFILE; - } else { + if (fdp->fd_lastfile >= NDFILE) { /* * Compute the smallest multiple of NDEXTENT needed * for the file descriptors currently in use, * allowing the table to shrink. */ - i = newfdp->fd_nfiles; - while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2) + i = fdp->fd_nfiles; + while (i >= 2 * NDEXTENT && i > fdp->fd_lastfile * 2) i /= 2; - newfdp->fd_ofiles = mallocarray(i, OFILESIZE, M_FILEDESC, M_WAITOK); + newfdp->fd_ofiles = mallocarray(i, OFILESIZE, M_FILEDESC, + M_WAITOK | M_ZERO); newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; + newfdp->fd_nfiles = i; } - 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 = mallocarray(NDHISLOTS(i), sizeof(u_int), - M_FILEDESC, M_WAITOK); - newfdp->fd_lomap = mallocarray(NDLOSLOTS(i), sizeof(u_int), - M_FILEDESC, M_WAITOK); + if (NDHISLOTS(newfdp->fd_nfiles) > NDHISLOTS(NDFILE)) { + newfdp->fd_himap = mallocarray(NDHISLOTS(newfdp->fd_nfiles), + sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); + newfdp->fd_lomap = mallocarray(NDLOSLOTS(newfdp->fd_nfiles), + sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); } - newfdp->fd_nfiles = i; - memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file *)); - memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char)); - memcpy(newfdp->fd_himap, fdp->fd_himap, NDHISLOTS(i) * sizeof(u_int)); - memcpy(newfdp->fd_lomap, fdp->fd_lomap, NDLOSLOTS(i) * sizeof(u_int)); - fdpunlock(fdp); + newfdp->fd_freefile = fdp->fd_freefile; + newfdp->fd_flags = fdp->fd_flags; + newfdp->fd_cmask = fdp->fd_cmask; + + for (i = 0; i <= fdp->fd_lastfile; i++) { + struct file *fp = fdp->fd_ofiles[i]; - fdplock(newfdp); - fpp = newfdp->fd_ofiles; - for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++) - if (*fpp != NULL) { + if (fp != NULL) { /* * XXX Gruesome hack. If count gets too high, fail * to copy an fd, since fdcopy()'s callers do not @@ -1082,22 +1072,18 @@ fdcopy(struct process *pr) * tied to the process that opened them to enforce * their internal consistency, so close them here. */ - if ((*fpp)->f_count == LONG_MAX-2 || - (*fpp)->f_type == DTYPE_KQUEUE) - fdremove(newfdp, i); - else - (*fpp)->f_count++; - } + if (fp->f_count == LONG_MAX-2 || + fp->f_type == DTYPE_KQUEUE) + continue; - /* finish cleaning up kq bits */ - if (newfdp->fd_knlistsize != -1) { - newfdp->fd_knlist = NULL; - newfdp->fd_knlistsize = -1; - newfdp->fd_knhash = NULL; - newfdp->fd_knhashmask = 0; + FREF(fp); + newfdp->fd_ofiles[i] = fp; + newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i]; + fd_used(newfdp, i); + } } + fdpunlock(fdp); - fdpunlock(newfdp); return (newfdp); } |