diff options
-rw-r--r-- | sys/conf/options | 3 | ||||
-rw-r--r-- | sys/conf/param.c | 8 | ||||
-rw-r--r-- | sys/kern/init_sysent.c | 1 | ||||
-rw-r--r-- | sys/kern/subr_param.c | 8 | ||||
-rw-r--r-- | sys/kern/syscalls.c | 1 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 4 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 404 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 3 | ||||
-rw-r--r-- | sys/sys/socket.h | 13 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 9 | ||||
-rw-r--r-- | sys/sys/syscall-hide.h | 1 | ||||
-rw-r--r-- | sys/sys/syscall.h | 3 | ||||
-rw-r--r-- | sys/sys/syscall.mk | 3 | ||||
-rw-r--r-- | sys/sys/sysproto.h | 10 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 4 |
15 files changed, 462 insertions, 13 deletions
diff --git a/sys/conf/options b/sys/conf/options index 65e1f8b..a664af2 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -1,4 +1,4 @@ -# $Id: options,v 1.105 1998/10/12 12:27:23 bde Exp $ +# $Id: options,v 1.106 1998/10/28 08:37:10 dfr Exp $ # # On the handling of kernel options # @@ -130,6 +130,7 @@ MSGSSZ opt_param.h MSGTQL opt_param.h NBUF opt_param.h NMBCLUSTERS opt_param.h +NSFBUFS opt_param.h SEMMAP opt_param.h SEMMNI opt_param.h SEMMNS opt_param.h diff --git a/sys/conf/param.c b/sys/conf/param.c index 4542984..6736b96 100644 --- a/sys/conf/param.c +++ b/sys/conf/param.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)param.c 8.3 (Berkeley) 8/20/94 - * $Id: param.c,v 1.29 1998/06/30 21:25:35 phk Exp $ + * $Id: param.c,v 1.30 1998/07/11 13:06:38 bde Exp $ */ #include "opt_sysvipc.h" @@ -95,6 +95,12 @@ int maxsockets = MAXSOCKETS; /* allocate 1/4th amount of virtual address space for mbufs XXX */ int nmbufs = NMBCLUSTERS * 4; +/* maximum # of sf_bufs (sendfile(2) zero-copy virtual buffers) */ +#ifndef NSFBUFS +#define NSFBUFS (512 + MAXUSERS * 16) +#endif +int nsfbufs = NSFBUFS; + /* * Values in support of System V compatible shared memory. XXX */ diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index d806c5b..a8307b1 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -355,4 +355,5 @@ struct sysent sysent[] = { { 1, (sy_call_t *)sched_get_priority_min }, /* 333 = sched_get_priority_min */ { 2, (sy_call_t *)sched_rr_get_interval }, /* 334 = sched_rr_get_interval */ { 2, (sy_call_t *)utrace }, /* 335 = utrace */ + { 8, (sy_call_t *)sendfile }, /* 336 = sendfile */ }; diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c index 4542984..6736b96 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)param.c 8.3 (Berkeley) 8/20/94 - * $Id: param.c,v 1.29 1998/06/30 21:25:35 phk Exp $ + * $Id: param.c,v 1.30 1998/07/11 13:06:38 bde Exp $ */ #include "opt_sysvipc.h" @@ -95,6 +95,12 @@ int maxsockets = MAXSOCKETS; /* allocate 1/4th amount of virtual address space for mbufs XXX */ int nmbufs = NMBCLUSTERS * 4; +/* maximum # of sf_bufs (sendfile(2) zero-copy virtual buffers) */ +#ifndef NSFBUFS +#define NSFBUFS (512 + MAXUSERS * 16) +#endif +int nsfbufs = NSFBUFS; + /* * Values in support of System V compatible shared memory. XXX */ diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 781cf4c..c5164a9 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -342,4 +342,5 @@ char *syscallnames[] = { "sched_get_priority_min", /* 333 = sched_get_priority_min */ "sched_rr_get_interval", /* 334 = sched_rr_get_interval */ "utrace", /* 335 = utrace */ + "sendfile", /* 336 = sendfile */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 769988b..c8d62cc 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ - $Id: syscalls.master,v 1.52 1998/06/07 17:11:40 dfr Exp $ + $Id: syscalls.master,v 1.53 1998/08/24 08:29:52 dfr Exp $ ; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 ; ; System call name/number master file. @@ -468,3 +468,5 @@ 333 STD POSIX { int sched_get_priority_min (int policy); } 334 STD POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } 335 STD BSD { int utrace(caddr_t addr, size_t len); } +336 STD BSD { int sendfile(int fd, int s, off_t offset, size_t nbytes, \ + struct sf_hdtr *hdtr, off_t *sbytes, int flags); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index a841bfa..f0cca24 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -2,6 +2,9 @@ * Copyright (c) 1982, 1986, 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * + * sendfile(2) and related extensions: + * Copyright (c) 1998, David Greenman. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -31,7 +34,7 @@ * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 - * $Id: uipc_syscalls.c,v 1.40 1998/06/10 10:30:23 dfr Exp $ + * $Id: uipc_syscalls.c,v 1.41 1998/08/23 03:06:59 wollman Exp $ */ #include "opt_compat.h" @@ -39,6 +42,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/kernel.h> #include <sys/sysproto.h> #include <sys/malloc.h> #include <sys/filedesc.h> @@ -51,9 +55,27 @@ #include <sys/socketvar.h> #include <sys/signalvar.h> #include <sys/uio.h> +#include <sys/vnode.h> +#include <sys/lock.h> +#include <sys/mount.h> #ifdef KTRACE #include <sys/ktrace.h> #endif +#include <vm/vm.h> +#include <vm/vm_prot.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_pager.h> +#include <vm/vm_pageout.h> +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> +#include <machine/limits.h> + +static void sf_buf_init(void *arg); +SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL) +static struct sf_buf *sf_buf_alloc(void); +static void sf_buf_ref(caddr_t addr, u_int size); +static void sf_buf_free(caddr_t addr, u_int size); static int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags)); static int recvit __P((struct proc *p, int s, struct msghdr *mp, @@ -65,6 +87,11 @@ static int getsockname1 __P((struct proc *p, struct getsockname_args *uap, static int getpeername1 __P((struct proc *p, struct getpeername_args *uap, int compat)); +static SLIST_HEAD(, sf_buf) sf_freelist; +static vm_offset_t sf_base; +static struct sf_buf *sf_bufs; +static int sf_buf_alloc_want; + /* * System call interface to the socket abstraction. */ @@ -1274,3 +1301,378 @@ getsock(fdp, fdes, fpp) *fpp = fp; return (0); } + +/* + * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-)) + * XXX - The sf_buf functions are currently private to sendfile(2), so have + * been made static, but may be useful in the future for doing zero-copy in + * other parts of the networking code. + */ +static void +sf_buf_init(void *arg) +{ + int i; + + SLIST_INIT(&sf_freelist); + sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE); + sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT); + bzero(sf_bufs, nsfbufs * sizeof(struct sf_buf)); + for (i = 0; i < nsfbufs; i++) { + sf_bufs[i].kva = sf_base + i * PAGE_SIZE; + SLIST_INSERT_HEAD(&sf_freelist, &sf_bufs[i], free_list); + } +} + +/* + * Get an sf_buf from the freelist. Will block if none are available. + */ +static struct sf_buf * +sf_buf_alloc() +{ + struct sf_buf *sf; + int s; + + s = splimp(); + while ((sf = SLIST_FIRST(&sf_freelist)) == NULL) { + sf_buf_alloc_want = 1; + tsleep(&sf_freelist, PVM, "sfbufa", 0); + } + SLIST_REMOVE_HEAD(&sf_freelist, free_list); + splx(s); + sf->refcnt = 1; + return (sf); +} + +#define dtosf(x) (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT]) +static void +sf_buf_ref(caddr_t addr, u_int size) +{ + struct sf_buf *sf; + + sf = dtosf(addr); + if (sf->refcnt == 0) + panic("sf_buf_ref: referencing a free sf_buf"); + sf->refcnt++; +} + +/* + * Lose a reference to an sf_buf. When none left, detach mapped page + * and release resources back to the system. + * + * Must be called at splimp. + */ +static void +sf_buf_free(caddr_t addr, u_int size) +{ + struct sf_buf *sf; + struct vm_page *m; + + sf = dtosf(addr); + if (sf->refcnt == 0) + panic("sf_buf_free: freeing free sf_buf"); + sf->refcnt--; + if (sf->refcnt == 0) { + pmap_qremove((vm_offset_t)addr, 1); + m = sf->m; + vm_page_unwire(m, 0); + /* + * Check for the object going away on us. This can + * happen since we don't hold a reference to it. + * If so, we're responsible for freeing the page. + */ + if (m->wire_count == 0 && m->object == NULL) + vm_page_free(m); + sf->m = NULL; + SLIST_INSERT_HEAD(&sf_freelist, sf, free_list); + if (sf_buf_alloc_want) { + sf_buf_alloc_want = 0; + wakeup(&sf_freelist); + } + } +} + +/* + * sendfile(2). + * int sendfile(int fd, int s, off_t offset, size_t nbytes, + * struct sf_hdtr *hdtr, off_t *sbytes, int flags) + * + * Send a file specified by 'fd' and starting at 'offset' to a socket + * specified by 's'. Send only 'nbytes' of the file or until EOF if + * nbytes == 0. Optionally add a header and/or trailer to the socket + * output. If specified, write the total number of bytes sent into *sbytes. + */ +int +sendfile(struct proc *p, struct sendfile_args *uap) +{ + struct file *fp; + struct filedesc *fdp = p->p_fd; + struct vnode *vp; + struct vm_object *obj; + struct socket *so; + struct mbuf *m; + struct sf_buf *sf; + struct vm_page *pg; + struct writev_args nuap; + struct sf_hdtr hdtr; + off_t off, xfsize, sbytes = 0; + int error = 0, i, s; + + /* + * Do argument checking. Must be a regular file in, stream + * type and connected socket out, positive offset. + */ + if (((u_int)uap->fd) >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[uap->fd]) == NULL || + (fp->f_flag & FREAD) == 0) { + error = EBADF; + goto done; + } + if (fp->f_type != DTYPE_VNODE) { + error = EINVAL; + goto done; + } + vp = (struct vnode *)fp->f_data; + obj = vp->v_object; + if (vp->v_type != VREG || obj == NULL) { + error = EINVAL; + goto done; + } + error = getsock(p->p_fd, uap->s, &fp); + if (error) + goto done; + so = (struct socket *)fp->f_data; + if (so->so_type != SOCK_STREAM) { + error = EINVAL; + goto done; + } + if ((so->so_state & SS_ISCONNECTED) == 0) { + error = ENOTCONN; + goto done; + } + if (uap->offset < 0) { + error = EINVAL; + goto done; + } + + /* + * If specified, get the pointer to the sf_hdtr struct for + * any headers/trailers. + */ + if (uap->hdtr != NULL) { + error = copyin(uap->hdtr, &hdtr, sizeof(hdtr)); + if (error) + goto done; + /* + * Send any headers. Wimp out and use writev(2). + */ + if (hdtr.headers != NULL) { + nuap.fd = uap->s; + nuap.iovp = hdtr.headers; + nuap.iovcnt = hdtr.hdr_cnt; + error = writev(p, &nuap); + if (error) + goto done; + sbytes += p->p_retval[0]; + } + } + + /* + * Protect against multiple writers to the socket. + */ + (void) sblock(&so->so_snd, M_WAITOK); + + /* + * Loop through the pages in the file, starting with the requested + * offset. Get a file page (do I/O if necessary), map the file page + * into an sf_buf, attach an mbuf header to the sf_buf, and queue + * it on the socket. + */ + for (off = uap->offset; ; off += xfsize, sbytes += xfsize) { + vm_pindex_t pindex; + + pindex = OFF_TO_IDX(off); +retry_lookup: + /* + * Calculate the amount to transfer. Not to exceed a page, + * the EOF, or the passed in nbytes. + */ + xfsize = obj->un_pager.vnp.vnp_size - off; + if (xfsize > PAGE_SIZE) + xfsize = PAGE_SIZE; + if (off & PAGE_MASK) + xfsize -= (off & PAGE_MASK); + if (uap->nbytes && xfsize > (uap->nbytes - sbytes)) + xfsize = uap->nbytes - sbytes; + if (xfsize <= 0) + break; + /* + * Attempt to look up the page. If the page doesn't exist or the + * part we're interested in isn't valid, then read it from disk. + * If some other part of the kernel has this page (i.e. it's busy), + * then disk I/O may be occuring on it, so wait and retry. + */ + pg = vm_page_lookup(obj, pindex); + if (pg == NULL || (!(pg->flags & PG_BUSY) && !pg->busy && + !vm_page_is_valid(pg, off & PAGE_MASK, xfsize))) { + struct uio auio; + struct iovec aiov; + int bsize; + + if (pg == NULL) { + pg = vm_page_alloc(obj, pindex, VM_ALLOC_NORMAL); + if (pg == NULL) { + VM_WAIT; + goto retry_lookup; + } + vm_page_flag_clear(pg, PG_BUSY); + } + /* + * Ensure that our page is still around when the I/O completes. + */ + vm_page_io_start(pg); + vm_page_wire(pg); + /* + * Get the page from backing store. + */ + bsize = vp->v_mount->mnt_stat.f_iosize; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = 0; + aiov.iov_len = MAXBSIZE; + auio.uio_resid = MAXBSIZE; + auio.uio_offset = trunc_page(off); + auio.uio_segflg = UIO_NOCOPY; + auio.uio_rw = UIO_READ; + auio.uio_procp = curproc; + vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, p); + error = VOP_READ(vp, &auio, IO_VMIO | ((MAXBSIZE / bsize) << 16), + p->p_ucred); + VOP_UNLOCK(vp, 0, p); + vm_page_io_finish(pg); + vm_page_flag_clear(pg, PG_ZERO); + if (error) { + vm_page_unwire(pg, 0); + /* + * See if anyone else might know about this page. + * If not and it is not valid, then free it. + */ + if (pg->wire_count == 0 && pg->valid == 0 && + pg->busy == 0 && !(pg->flags & PG_BUSY) && + pg->hold_count == 0) + vm_page_free(pg); + sbunlock(&so->so_snd); + goto done; + } + } else { + if ((pg->flags & PG_BUSY) || pg->busy) { + s = splvm(); + if ((pg->flags & PG_BUSY) || pg->busy) { + /* + * Page is busy. Wait and retry. + */ + vm_page_flag_set(pg, PG_WANTED); + tsleep(pg, PVM, "sfpbsy", 0); + splx(s); + goto retry_lookup; + } + splx(s); + } + /* + * Protect from having the page ripped out from beneath us. + */ + vm_page_wire(pg); + } + /* + * Allocate a kernel virtual page and insert the physical page + * into it. + */ + sf = sf_buf_alloc(); + sf->m = pg; + pmap_qenter(sf->kva, &pg, 1); + /* + * Get an mbuf header and set it up as having external storage. + */ + MGETHDR(m, M_WAIT, MT_DATA); + m->m_ext.ext_free = sf_buf_free; + m->m_ext.ext_ref = sf_buf_ref; + m->m_ext.ext_buf = (void *)sf->kva; + m->m_ext.ext_size = PAGE_SIZE; + m->m_data = (char *) sf->kva + (off & PAGE_MASK); + m->m_flags |= M_EXT; + m->m_pkthdr.len = m->m_len = xfsize; + /* + * Add the buffer to the socket buffer chain. + */ + s = splnet(); +retry_space: + /* + * Make sure that the socket is still able to take more data. + * CANTSENDMORE being true usually means that the connection + * was closed. so_error is true when an error was sensed after + * a previous send. + * The state is checked after the page mapping and buffer + * allocation above since those operations may block and make + * any socket checks stale. From this point forward, nothing + * blocks before the pru_send (or more accurately, any blocking + * results in a loop back to here to re-check). + */ + if ((so->so_state & SS_CANTSENDMORE) || so->so_error) { + if (so->so_state & SS_CANTSENDMORE) { + error = EPIPE; + } else { + error = so->so_error; + so->so_error = 0; + } + m_freem(m); + sbunlock(&so->so_snd); + splx(s); + goto done; + } + /* + * Wait for socket space to become available. We do this just + * after checking the connection state above in order to avoid + * a race condition with sbwait(). + */ + if (sbspace(&so->so_snd) <= 0) { + error = sbwait(&so->so_snd); + /* + * An error from sbwait usually indicates that we've + * been interrupted by a signal. If we've sent anything + * then return bytes sent, otherwise return the error. + */ + if (error) { + m_freem(m); + sbunlock(&so->so_snd); + splx(s); + goto done; + } + goto retry_space; + } + error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, p); + splx(s); + if (error) { + sbunlock(&so->so_snd); + goto done; + } + } + sbunlock(&so->so_snd); + + /* + * Send trailers. Wimp out and use writev(2). + */ + if (uap->hdtr != NULL && hdtr.trailers != NULL) { + nuap.fd = uap->s; + nuap.iovp = hdtr.trailers; + nuap.iovcnt = hdtr.trl_cnt; + error = writev(p, &nuap); + if (error) + goto done; + sbytes += p->p_retval[0]; + } + +done: + if (uap->sbytes != NULL) { + copyout(&sbytes, uap->sbytes, sizeof(off_t)); + } + return (error); +} diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 8dcebae..77a44ef 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 - * $Id: mbuf.h,v 1.28 1998/08/23 03:07:17 wollman Exp $ + * $Id: mbuf.h,v 1.29 1998/08/24 07:47:38 dfr Exp $ */ #ifndef _SYS_MBUF_H_ @@ -390,6 +390,7 @@ extern char *mclrefcnt; /* cluster reference counts */ extern struct mbstat mbstat; extern int nmbclusters; extern int nmbufs; +extern int nsfbufs; extern struct mbuf *mmbfree; extern union mcluster *mclfree; extern int max_linkhdr; /* largest link-level header */ diff --git a/sys/sys/socket.h b/sys/sys/socket.h index 3c3d311..b7da75a 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)socket.h 8.4 (Berkeley) 2/21/94 - * $Id: socket.h,v 1.25 1998/09/12 21:14:25 wollman Exp $ + * $Id: socket.h,v 1.26 1998/09/15 11:44:44 phk Exp $ */ #ifndef _SYS_SOCKET_H_ @@ -363,6 +363,16 @@ struct omsghdr { #define SHUT_WR 1 /* shut down the writing side */ #define SHUT_RDWR 2 /* shut down both sides */ +/* + * sendfile(2) header/trailer struct + */ +struct sf_hdtr { + struct iovec *headers; /* pointer to an array of header struct iovec's */ + int hdr_cnt; /* number of header iovec's */ + struct iovec *trailers; /* pointer to an array of trailer struct iovec's */ + int trl_cnt; /* number of trailer iovec's */ +}; + #ifndef KERNEL #include <sys/cdefs.h> @@ -382,6 +392,7 @@ ssize_t send __P((int, const void *, size_t, int)); ssize_t sendto __P((int, const void *, size_t, int, const struct sockaddr *, int)); ssize_t sendmsg __P((int, const struct msghdr *, int)); +int sendfile __P((int, int, off_t, size_t, struct sf_hdtr *, off_t *, int)); int setsockopt __P((int, int, int, const void *, int)); int shutdown __P((int, int)); int socket __P((int, int, int)); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 86c17ed..3a53ca7 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)socketvar.h 8.3 (Berkeley) 2/19/95 - * $Id: socketvar.h,v 1.28 1998/06/07 17:13:03 dfr Exp $ + * $Id: socketvar.h,v 1.29 1998/08/23 03:07:17 wollman Exp $ */ #ifndef _SYS_SOCKETVAR_H_ @@ -256,6 +256,13 @@ struct sockopt { struct proc *sopt_p; /* calling process or null if kernel */ }; +struct sf_buf { + SLIST_ENTRY(sf_buf) free_list; /* list of free buffer slots */ + int refcnt; /* reference count */ + struct vm_page *m; /* currently mapped page */ + vm_offset_t kva; /* va of mapping */ +}; + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_PCB); MALLOC_DECLARE(M_SONAME); diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index dd8fab9..060d955 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -247,3 +247,4 @@ HIDE_POSIX(sched_get_priority_max) HIDE_POSIX(sched_get_priority_min) HIDE_POSIX(sched_rr_get_interval) HIDE_BSD(utrace) +HIDE_BSD(sendfile) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index ae58e24..714573d 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -253,4 +253,5 @@ #define SYS_sched_get_priority_min 333 #define SYS_sched_rr_get_interval 334 #define SYS_utrace 335 -#define SYS_MAXSYSCALL 336 +#define SYS_sendfile 336 +#define SYS_MAXSYSCALL 337 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 5d5bd0f..557f5a9 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -208,4 +208,5 @@ MIASM = \ sched_get_priority_max.o \ sched_get_priority_min.o \ sched_rr_get_interval.o \ - utrace.o + utrace.o \ + sendfile.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 40ee5bd..7286f50 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -879,6 +879,15 @@ struct utrace_args { caddr_t addr; char addr_[PAD_(caddr_t)]; size_t len; char len_[PAD_(size_t)]; }; +struct sendfile_args { + int fd; char fd_[PAD_(int)]; + int s; char s_[PAD_(int)]; + off_t offset; char offset_[PAD_(off_t)]; + size_t nbytes; char nbytes_[PAD_(size_t)]; + struct sf_hdtr * hdtr; char hdtr_[PAD_(struct sf_hdtr *)]; + off_t * sbytes; char sbytes_[PAD_(off_t *)]; + int flags; char flags_[PAD_(int)]; +}; int nosys __P((struct proc *, struct nosys_args *)); void exit __P((struct proc *, struct rexit_args *)) __dead2; int fork __P((struct proc *, struct fork_args *)); @@ -1084,6 +1093,7 @@ int sched_get_priority_max __P((struct proc *, struct sched_get_priority_max_arg int sched_get_priority_min __P((struct proc *, struct sched_get_priority_min_args *)); int sched_rr_get_interval __P((struct proc *, struct sched_rr_get_interval_args *)); int utrace __P((struct proc *, struct utrace_args *)); +int sendfile __P((struct proc *, struct sendfile_args *)); #ifdef COMPAT_43 diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 1bb7a40..1ea7978 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.133 1998/10/25 17:44:58 phk Exp $ + * $Id: vm_object.c,v 1.134 1998/10/27 13:22:51 dg Exp $ */ /* @@ -461,8 +461,6 @@ vm_object_terminate(object) vm_page_free(p); cnt.v_pfree++; } else { - if (!(p->flags & PG_FICTITIOUS)) - printf("vm_object_terminate: not freeing wired page; wire_count=%d\n", p->wire_count); vm_page_busy(p); vm_page_remove(p); } |