--- //depot/projects/smpng/sys/compat/freebsd32/freebsd32_misc.c 2005/06/29 18:47:53 +++ //depot/user/jhb/ktrace/compat/freebsd32/freebsd32_misc.c 2005/07/01 19:44:15 @@ -764,6 +764,34 @@ } int +freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap) +{ + struct uio *auio; + int error; + + error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_preadv(td, uap->fd, auio, uap->offset); + free(auio, M_IOV); + return (error); +} + +int +freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) +{ + struct uio *auio; + int error; + + error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_pwritev(td, uap->fd, auio, uap->offset); + free(auio, M_IOV); + return (error); +} + +int freebsd32_settimeofday(struct thread *td, struct freebsd32_settimeofday_args *uap) { --- //depot/projects/smpng/sys/compat/freebsd32/syscalls.master 2005/06/15 20:53:05 +++ //depot/user/jhb/ktrace/compat/freebsd32/syscalls.master 2005/07/01 18:47:18 @@ -482,8 +482,15 @@ 286 AUE_NULL UNIMPL nosys 287 AUE_NULL UNIMPL nosys 288 AUE_NULL UNIMPL nosys -289 AUE_NULL UNIMPL nosys -290 AUE_NULL UNIMPL nosys +; 289 and 290 from NetBSD (OpenBSD: 267 and 268) +289 AUE_NULL MSTD { ssize_t freebsd32_preadv(int fd, \ + struct iovec32 *iovp, \ + u_int iovcnt, off_t offset); } +; XXX note - bigendian is different +290 AUE_NULL MSTD { ssize_t freebsd32_pwritev(int fd, \ + struct iovec32 *iovp, \ + u_int iovcnt, off_t offset); } +; XXX note - bigendian is different 291 AUE_NULL UNIMPL nosys 292 AUE_NULL UNIMPL nosys 293 AUE_NULL UNIMPL nosys --- //depot/projects/smpng/sys/kern/sys_generic.c 2005/04/01 18:38:57 +++ //depot/user/jhb/ktrace/kern/sys_generic.c 2005/07/01 20:21:46 @@ -76,10 +76,10 @@ static int pollscan(struct thread *, struct pollfd *, u_int); static int selscan(struct thread *, fd_mask **, fd_mask **, int); -static int dofileread(struct thread *, struct file *, int, void *, - size_t, off_t, int); -static int dofilewrite(struct thread *, struct file *, int, - const void *, size_t, off_t, int); +static int dofileread(struct thread *, int, struct file *, struct uio *, + off_t, int); +static int dofilewrite(struct thread *, int, struct file *, struct uio *, + off_t, int); static void doselwakeup(struct selinfo *, int); /* @@ -100,19 +100,24 @@ struct thread *td; struct read_args *uap; { - struct file *fp; + struct uio auio; + struct iovec aiov; int error; - if ((error = fget_read(td, uap->fd, &fp)) == 0) { - error = dofileread(td, fp, uap->fd, uap->buf, - uap->nbyte, (off_t)-1, 0); - fdrop(fp, td); - } + if (uap->nbyte > INT_MAX) + return (EINVAL); + aiov.iov_base = uap->buf; + aiov.iov_len = uap->nbyte; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = uap->nbyte; + auio.uio_segflg = UIO_USERSPACE; + error = kern_readv(td, uap->fd, &auio); return(error); } /* - * Pread system call + * Positioned read system call */ #ifndef _SYS_SYSPROTO_H_ struct pread_args { @@ -131,79 +136,20 @@ struct thread *td; struct pread_args *uap; { - struct file *fp; - int error; - - if ((error = fget_read(td, uap->fd, &fp)) != 0) - return (error); - if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) - error = ESPIPE; - else if (uap->offset < 0 && fp->f_vnode->v_type != VCHR) - error = EINVAL; - else { - error = dofileread(td, fp, uap->fd, uap->buf, uap->nbyte, - uap->offset, FOF_OFFSET); - } - fdrop(fp, td); - return(error); -} - -/* - * Code common for read and pread - */ -static int -dofileread(td, fp, fd, buf, nbyte, offset, flags) - struct thread *td; - struct file *fp; - int fd, flags; - void *buf; - size_t nbyte; - off_t offset; -{ struct uio auio; struct iovec aiov; - ssize_t cnt; - long error = 0; -#ifdef KTRACE - struct uio *ktruio = NULL; -#endif + int error; - /* Finish zero length reads right here */ - if (nbyte == 0) { - td->td_retval[0] = 0; - return(0); - } - aiov.iov_base = buf; - aiov.iov_len = nbyte; + if (uap->nbyte > INT_MAX) + return (EINVAL); + aiov.iov_base = uap->buf; + aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - auio.uio_offset = offset; - if (nbyte > INT_MAX) - return (EINVAL); - auio.uio_resid = nbyte; - auio.uio_rw = UIO_READ; + auio.uio_resid = uap->nbyte; auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; -#ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) - ktruio = cloneuio(&auio); -#endif - cnt = nbyte; - - if ((error = fo_read(fp, &auio, td->td_ucred, flags, td))) { - if (auio.uio_resid != cnt && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) - error = 0; - } - cnt -= auio.uio_resid; -#ifdef KTRACE - if (ktruio != NULL) { - ktruio->uio_resid = cnt; - ktrgenio(fd, UIO_READ, ktruio, error); - } -#endif - td->td_retval[0] = cnt; - return (error); + error = kern_preadv(td, uap->fd, &auio, uap->offset); + return(error); } /* @@ -237,29 +183,100 @@ kern_readv(struct thread *td, int fd, struct uio *auio) { struct file *fp; - long cnt; int error; -#ifdef KTRACE - struct uio *ktruio = NULL; + + error = fget_read(td, fd, &fp); + if (error) + return (error); + error = dofileread(td, fd, fp, auio, (off_t)-1, 0); + fdrop(fp, td); + return (error); +} + +/* + * Scatter positioned read system call. + */ +#ifndef _SYS_SYSPROTO_H_ +struct preadv_args { + int fd; + struct iovec *iovp; + u_int iovcnt; + off_t offset; +}; #endif +/* + * MPSAFE + */ +int +preadv(struct thread *td, struct preadv_args *uap) +{ + struct uio *auio; + int error; + error = copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_preadv(td, uap->fd, auio, uap->offset); + free(auio, M_IOV); + return (error); +} + +int +kern_preadv(td, fd, auio, offset) + struct thread *td; + int fd; + struct uio *auio; + off_t offset; +{ + struct file *fp; + int error; + error = fget_read(td, fd, &fp); if (error) return (error); + if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) + error = ESPIPE; + else if (offset < 0 && fp->f_vnode->v_type != VCHR) + error = EINVAL; + else + error = dofileread(td, fd, fp, auio, offset, FOF_OFFSET); + fdrop(fp, td); + return (error); +} + +/* + * Common code for readv and preadv that reads data in + * from a file using the passed in uio, offset, and flags. + */ +static int +dofileread(td, fd, fp, auio, offset, flags) + struct thread *td; + int fd; + struct file *fp; + struct uio *auio; + off_t offset; + int flags; +{ + ssize_t cnt; + int error; +#ifdef KTRACE + struct uio *ktruio = NULL; +#endif + /* Finish zero length reads right here */ if (auio->uio_resid == 0) { td->td_retval[0] = 0; - fdrop(fp, td); return(0); } auio->uio_rw = UIO_READ; + auio->uio_offset = offset; auio->uio_td = td; #ifdef KTRACE if (KTRPOINT(td, KTR_GENIO)) ktruio = cloneuio(auio); #endif cnt = auio->uio_resid; - if ((error = fo_read(fp, auio, td->td_ucred, 0, td))) { + if ((error = fo_read(fp, auio, td->td_ucred, flags, td))) { if (auio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; @@ -272,7 +289,6 @@ } #endif td->td_retval[0] = cnt; - fdrop(fp, td); return (error); } @@ -294,21 +310,24 @@ struct thread *td; struct write_args *uap; { - struct file *fp; + struct uio auio; + struct iovec aiov; int error; - if ((error = fget_write(td, uap->fd, &fp)) == 0) { - error = dofilewrite(td, fp, uap->fd, uap->buf, uap->nbyte, - (off_t)-1, 0); - fdrop(fp, td); - } else { - error = EBADF; /* XXX this can't be right */ - } + if (uap->nbyte > INT_MAX) + return (EINVAL); + aiov.iov_base = (void *)(uintptr_t)uap->buf; + aiov.iov_len = uap->nbyte; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = uap->nbyte; + auio.uio_segflg = UIO_USERSPACE; + error = kern_writev(td, uap->fd, &auio); return(error); } /* - * Pwrite system call + * Positioned write system call */ #ifndef _SYS_SYSPROTO_H_ struct pwrite_args { @@ -327,80 +346,20 @@ struct thread *td; struct pwrite_args *uap; { - struct file *fp; - int error; - - if ((error = fget_write(td, uap->fd, &fp)) == 0) { - if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) - error = ESPIPE; - else if (uap->offset < 0 && fp->f_vnode->v_type != VCHR) - error = EINVAL; - else { - error = dofilewrite(td, fp, uap->fd, uap->buf, - uap->nbyte, uap->offset, FOF_OFFSET); - } - fdrop(fp, td); - } else { - error = EBADF; /* this can't be right */ - } - return(error); -} - -static int -dofilewrite(td, fp, fd, buf, nbyte, offset, flags) - struct thread *td; - struct file *fp; - int fd, flags; - const void *buf; - size_t nbyte; - off_t offset; -{ struct uio auio; struct iovec aiov; - ssize_t cnt; - long error = 0; -#ifdef KTRACE - struct uio *ktruio = NULL; -#endif + int error; - aiov.iov_base = (void *)(uintptr_t)buf; - aiov.iov_len = nbyte; + if (uap->nbyte > INT_MAX) + return (EINVAL); + aiov.iov_base = (void *)(uintptr_t)uap->buf; + aiov.iov_len = uap->nbyte; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - auio.uio_offset = offset; - if (nbyte > INT_MAX) - return (EINVAL); - auio.uio_resid = nbyte; - auio.uio_rw = UIO_WRITE; + auio.uio_resid = uap->nbyte; auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; -#ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) - ktruio = cloneuio(&auio); -#endif - cnt = nbyte; - if (fp->f_type == DTYPE_VNODE) - bwillwrite(); - if ((error = fo_write(fp, &auio, td->td_ucred, flags, td))) { - if (auio.uio_resid != cnt && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) - error = 0; - /* Socket layer is responsible for issuing SIGPIPE. */ - if (error == EPIPE && fp->f_type != DTYPE_SOCKET) { - PROC_LOCK(td->td_proc); - psignal(td->td_proc, SIGPIPE); - PROC_UNLOCK(td->td_proc); - } - } - cnt -= auio.uio_resid; -#ifdef KTRACE - if (ktruio != NULL) { - ktruio->uio_resid = cnt; - ktrgenio(fd, UIO_WRITE, ktruio, error); - } -#endif - td->td_retval[0] = cnt; - return (error); + error = kern_pwritev(td, uap->fd, &auio, uap->offset); + return(error); } /* @@ -434,17 +393,89 @@ kern_writev(struct thread *td, int fd, struct uio *auio) { struct file *fp; - long cnt; + int error; + + error = fget_write(td, fd, &fp); + if (error) + return (EBADF); /* XXX this can't be right */ + error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0); + fdrop(fp, td); + return (error); +} + +/* + * Gather positioned write system call + */ +#ifndef _SYS_SYSPROTO_H_ +struct pwritev_args { + int fd; + struct iovec *iovp; + u_int iovcnt; + off_t offset; +}; +#endif +/* + * MPSAFE + */ +int +pwritev(struct thread *td, struct pwritev_args *uap) +{ + struct uio *auio; + int error; + + error = copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_pwritev(td, uap->fd, auio, uap->offset); + free(auio, M_IOV); + return (error); +} + +int +kern_pwritev(td, fd, auio, offset) + struct thread *td; + struct uio *auio; + int fd; + off_t offset; +{ + struct file *fp; + int error; + + error = fget_write(td, fd, &fp); + if (error) + return (EBADF); /* XXX this can't be right */ + if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) + error = ESPIPE; + else if (offset < 0 && fp->f_vnode->v_type != VCHR) + error = EINVAL; + else + error = dofilewrite(td, fd, fp, auio, offset, FOF_OFFSET); + fdrop(fp, td); + return (error); +} + +/* + * Common code for writev and pwritev that writes data to + * a file using the passed in uio, offset, and flags. + */ +static int +dofilewrite(td, fd, fp, auio, offset, flags) + struct thread *td; + int fd; + struct file *fp; + struct uio *auio; + off_t offset; + int flags; +{ + ssize_t cnt; int error; #ifdef KTRACE struct uio *ktruio = NULL; #endif - error = fget_write(td, fd, &fp); - if (error) - return (EBADF); auio->uio_rw = UIO_WRITE; auio->uio_td = td; + auio->uio_offset = offset; #ifdef KTRACE if (KTRPOINT(td, KTR_GENIO)) ktruio = cloneuio(auio); @@ -452,10 +483,11 @@ cnt = auio->uio_resid; if (fp->f_type == DTYPE_VNODE) bwillwrite(); - if ((error = fo_write(fp, auio, td->td_ucred, 0, td))) { + if ((error = fo_write(fp, auio, td->td_ucred, flags, td))) { if (auio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; + /* Socket layer is responsible for issuing SIGPIPE. */ if (error == EPIPE) { PROC_LOCK(td->td_proc); psignal(td->td_proc, SIGPIPE); @@ -470,7 +502,6 @@ } #endif td->td_retval[0] = cnt; - fdrop(fp, td); return (error); } --- //depot/projects/smpng/sys/kern/syscalls.master 2005/06/15 20:53:05 +++ //depot/user/jhb/ktrace/kern/syscalls.master 2005/07/01 18:47:18 @@ -502,8 +502,11 @@ 286 AUE_NULL UNIMPL nosys 287 AUE_NULL UNIMPL nosys 288 AUE_NULL UNIMPL nosys -289 AUE_NULL UNIMPL nosys -290 AUE_NULL UNIMPL nosys +; 289 and 290 from NetBSD (OpenBSD: 267 and 268) +289 AUE_NULL MSTD { ssize_t preadv(int fd, struct iovec *iovp, \ + u_int iovcnt, off_t offset); } +290 AUE_NULL MSTD { ssize_t pwritev(int fd, struct iovec *iovp, \ + u_int iovcnt, off_t offset); } 291 AUE_NULL UNIMPL nosys 292 AUE_NULL UNIMPL nosys 293 AUE_NULL UNIMPL nosys --- //depot/projects/smpng/sys/sys/syscallsubr.h 2005/06/15 20:53:05 +++ //depot/user/jhb/ktrace/sys/syscallsubr.h 2005/07/01 19:44:15 @@ -98,8 +98,10 @@ int flags, int mode); int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name); +int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data); +int kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, enum uio_seg bufseg, int count); int kern_readv(struct thread *td, int fd, struct uio *auio); --- //depot/projects/smpng/sys/sys/uio.h 2005/01/07 18:05:05 +++ //depot/user/jhb/ktrace/sys/uio.h 2005/07/01 18:47:18 @@ -42,6 +42,11 @@ #define _SSIZE_T_DECLARED #endif +#ifndef _OFF_T_DECLARED +typedef __off_t off_t; +#define _OFF_T_DECLARED +#endif + #if __BSD_VISIBLE enum uio_rw { UIO_READ, UIO_WRITE }; @@ -101,6 +106,8 @@ __BEGIN_DECLS ssize_t readv(int, const struct iovec *, int); ssize_t writev(int, const struct iovec *, int); +ssize_t preadv(int, const struct iovec *, int, off_t); +ssize_t pwritev(int, const struct iovec *, int, off_t); __END_DECLS #endif /* _KERNEL */