From marcolz@stack.nl  Tue Apr 26 13:13:15 2005
Return-Path: <marcolz@stack.nl>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 3AEDD16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 26 Apr 2005 13:13:15 +0000 (GMT)
Received: from mailhost.stack.nl (vaak.stack.nl [131.155.140.140])
	by mx1.FreeBSD.org (Postfix) with ESMTP id EE33943D2F
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 26 Apr 2005 13:13:13 +0000 (GMT)
	(envelope-from marcolz@stack.nl)
Received: from hammer.stack.nl (hammer.stack.nl [IPv6:2001:610:1108:5010::153])
	by mailhost.stack.nl (Postfix) with ESMTP id F00381F023
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 26 Apr 2005 15:13:12 +0200 (CEST)
Received: by hammer.stack.nl (Postfix, from userid 333)
	id D7588663D; Tue, 26 Apr 2005 15:13:12 +0200 (CEST)
Message-Id: <20050426131312.D7588663D@hammer.stack.nl>
Date: Tue, 26 Apr 2005 15:13:12 +0200 (CEST)
From: Marc Olzheim <marcolz@stack.nl>
Reply-To: Marc Olzheim <marcolz@stack.nl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] add preadv() and pwritev() system calls
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         80362
>Category:       kern
>Synopsis:       [PATCH] add preadv() and pwritev() system calls
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 26 13:20:30 GMT 2005
>Closed-Date:    Thu Sep 22 18:21:09 GMT 2005
>Last-Modified:  Thu Sep 22 19:00:27 GMT 2005
>Originator:     Marc Olzheim
>Release:        FreeBSD 5.4-STABLE amd64
>Organization:
ilse media
>Environment:
FreeBSD 5.4-STABLE and FreeBSD 6.0-CURRENT


>Description:
	FreeBSD lacks preadv() and pwritev(). Since all underlying code
	already supports the functionality it is very easy to add.
	NetBSD and OpenBSD have had these calls, that are useful in
	multi-threaded fileaccess, for years now and for orthogonality
	it's nice to have them as well.
>How-To-Repeat:
>Fix:

	Patches for 5.4-STABLE and 6-CURRENT to follow:

5.4-STABLE.patch:
--- /usr/src/lib/libc/sys/read.2	Sat Nov 13 12:55:41 2004
+++ /usr/src/lib/libc/sys/read.2	Tue Apr 26 14:01:23 2005
@@ -38,7 +38,8 @@
 .Sh NAME
 .Nm read ,
 .Nm readv ,
-.Nm pread
+.Nm pread ,
+.Nm preadv
 .Nd read input
 .Sh LIBRARY
 .Lb libc
@@ -49,9 +50,11 @@
 .Ft ssize_t
 .Fn read "int d" "void *buf" "size_t nbytes"
 .Ft ssize_t
+.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
 .Fn readv "int d" "const struct iovec *iov" "int iovcnt"
 .Ft ssize_t
-.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Fn preadv "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
 .Sh DESCRIPTION
 The
 .Fn read
@@ -73,12 +76,16 @@
 array: iov[0], iov[1], ..., iov[iovcnt\|\-\|1].
 The
 .Fn pread
-system call
-performs the same function, but reads from the specified position in
+and
+.Fn preadv
+system calls
+perform the same functions, but read from the specified position in
 the file without modifying the file pointer.
 .Pp
 For
-.Fn readv ,
+.Fn readv
+and
+.Fn preadv ,
 the
 .Fa iovec
 structure is defined as:
@@ -119,8 +126,9 @@
 Upon successful completion,
 .Fn read ,
 .Fn readv ,
-and
 .Fn pread
+and
+.Fn preadv
 return the number of bytes actually read and placed in the buffer.
 The system guarantees to read the number of bytes requested if
 the descriptor references a normal file that has that many bytes left
@@ -137,8 +145,9 @@
 The
 .Fn read ,
 .Fn readv ,
-and
 .Fn pread
+and
+.Fn preadv
 system calls
 will succeed unless:
 .Bl -tag -width Er
@@ -184,6 +193,8 @@
 .Pp
 In addition,
 .Fn readv
+and
+.Fn preadv
 may return one of the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
@@ -212,7 +223,9 @@
 .Pp
 The
 .Fn pread
-system call may also return the following errors:
+and
+.Fn preadv
+system calls may also return the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The
@@ -244,6 +257,10 @@
 system calls are expected to conform to
 .St -xpg4.2 .
 .Sh HISTORY
+The
+.Fn preadv
+system call appeared in
+.Fx 5.4 .
 The
 .Fn pread
 function appeared in
--- /usr/src/lib/libc/sys/write.2	Sat Nov 13 12:55:41 2004
+++ /usr/src/lib/libc/sys/write.2	Tue Apr 26 13:59:59 2005
@@ -49,9 +49,11 @@
 .Ft ssize_t
 .Fn write "int d" "const void *buf" "size_t nbytes"
 .Ft ssize_t
+.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
 .Fn writev "int d" "const struct iovec *iov" "int iovcnt"
 .Ft ssize_t
-.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Fn pwritev "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
 .Sh DESCRIPTION
 The
 .Fn write
@@ -73,12 +75,16 @@
 array: iov[0], iov[1], ..., iov[iovcnt\|-\|1].
 The
 .Fn pwrite
-system call
-performs the same function, but writes to the specified position in
+and
+.Fn pwritev
+system calls
+perform the same functions, but write to the specified position in
 the file without modifying the file pointer.
 .Pp
 For
-.Fn writev ,
+.Fn writev
+and
+.Fn pwritev,
 the
 .Fa iovec
 structure is defined as:
@@ -143,8 +149,9 @@
 The
 .Fn write ,
 .Fn writev ,
-and
 .Fn pwrite
+and
+.Fn pwritev
 system calls
 will fail and the file pointer will remain unchanged if:
 .Bl -tag -width Er
@@ -196,6 +203,8 @@
 .Pp
 In addition,
 .Fn writev
+and
+.Fn pwritev
 may return one of the following errors:
 .Bl -tag -width Er
 .It Bq Er EDESTADDRREQ
@@ -228,7 +237,9 @@
 .Pp
 The
 .Fn pwrite
-system call may also return the following errors:
+and
+.Fn pwritev
+system calls may also return the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The
@@ -255,6 +266,10 @@
 system calls are expected to conform to
 .St -xpg4.2 .
 .Sh HISTORY
+The
+.Fn pwritev
+system call appeared in
+.Fx 5.4 .
 The
 .Fn pwrite
 function appeared in
--- /usr/src/sys/sys/syscallsubr.h	Tue Apr 26 13:35:50 2005
+++ /usr/src/sys/sys/syscallsubr.h	Tue Apr 26 13:36:56 2005
@@ -91,8 +91,12 @@
 	    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 flags);
 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 flags);
 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);
--- /usr/src/sys/sys/uio.h	Tue Feb  1 00:26:57 2005
+++ /usr/src/sys/sys/uio.h	Tue Apr 26 11:31:56 2005
@@ -102,6 +102,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 */
--- /usr/src/sys/kern/syscalls.master	Tue Apr 26 11:28:55 2005
+++ /usr/src/sys/kern/syscalls.master	Tue Apr 26 11:31:56 2005
@@ -411,8 +411,11 @@
 286	UNIMPL	nosys
 287	UNIMPL	nosys
 288	UNIMPL	nosys
-289	UNIMPL	nosys
-290	UNIMPL	nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289	MSTD	{ ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt,\
+		    off_t offset); }
+290	MSTD	{ ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt,\
+		    off_t offset); }
 291	UNIMPL	nosys
 292	UNIMPL	nosys
 293	UNIMPL	nosys
--- /usr/src/sys/kern/sys_generic.c	Tue Apr 26 11:28:55 2005
+++ /usr/src/sys/kern/sys_generic.c	Tue Apr 26 13:37:57 2005
@@ -232,9 +232,47 @@
 	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, FOF_OFFSET);
+	free(auio, M_IOV);
+	return (error);
+}
+
 int
 kern_readv(struct thread *td, int fd, struct uio *auio)
 {
+	return (kern_preadv(td, fd, auio, (off_t)-1, 0));
+}
+
+int
+kern_preadv(td, fd, auio, offset, flags)
+	struct thread *td;
+	struct uio *auio;
+	int fd, flags;
+	off_t offset;
+{
 	struct file *fp;
 	long cnt;
 	int error;
@@ -252,13 +290,14 @@
 		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;
@@ -428,9 +467,47 @@
 	return (error);
 }
 
+/*
+ * Gather posiotioned 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, FOF_OFFSET);
+	free(auio, M_IOV);
+	return (error);
+}
+
 int
 kern_writev(struct thread *td, int fd, struct uio *auio)
 {
+	return (kern_pwritev(td, fd, auio, (off_t)-1 , 0));
+}
+
+int
+kern_pwritev(td, fd, auio, offset, flags)
+	struct thread *td;
+	struct uio *auio;
+	int fd, flags;
+	off_t offset;
+{
 	struct file *fp;
 	long cnt;
 	int error;
@@ -443,6 +520,7 @@
 		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);
@@ -450,7 +528,7 @@
 	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;
--- /usr/src/sys/compat/freebsd32/syscalls.master	Tue Apr 26 11:28:51 2005
+++ /usr/src/sys/compat/freebsd32/syscalls.master	Tue Apr 26 13:52:46 2005
@@ -406,8 +406,13 @@
 286	UNIMPL	nosys
 287	UNIMPL	nosys
 288	UNIMPL	nosys
-289	UNIMPL	nosys
-290	UNIMPL	nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289	STD { ssize_t freebsd32_preadv(int fd, struct iovec32 *iovp,\
+		    u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
+290	STD { ssize_t freebsd32_pwritev(int fd, struct iovec32 *iovp,\
+		    u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
 291	UNIMPL	nosys
 292	UNIMPL	nosys
 293	UNIMPL	nosys
--- /usr/src/sys/compat/freebsd32/freebsd32_misc.c	Tue Apr 26 13:38:38 2005
+++ /usr/src/sys/compat/freebsd32/freebsd32_misc.c	Tue Apr 26 13:45:17 2005
@@ -694,7 +694,7 @@
 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
 	if (error)
 		return (error);
-	error = kern_readv(td, uap->fd, auio);
+	error = kern_preadv(td, uap->fd, auio, (off_t)-1, 0);
 	free(auio, M_IOV);
 	return (error);
 }
@@ -708,7 +708,35 @@
 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
 	if (error)
 		return (error);
-	error = kern_writev(td, uap->fd, auio);
+	error = kern_pwritev(td, uap->fd, auio, (off_t)-1, 0);
+	free(auio, M_IOV);
+	return (error);
+}
+
+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, FOF_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, FOF_OFFSET);
 	free(auio, M_IOV);
 	return (error);
 }

6-CURRENT.patch:

--- /usr/src/lib/libc/sys/read.2	Tue Apr 26 12:15:30 2005
+++ /usr/src/lib/libc/sys/read.2	Tue Apr 26 14:03:07 2005
@@ -38,7 +38,8 @@
 .Sh NAME
 .Nm read ,
 .Nm readv ,
-.Nm pread
+.Nm pread ,
+.Nm preadv
 .Nd read input
 .Sh LIBRARY
 .Lb libc
@@ -49,9 +50,11 @@
 .Ft ssize_t
 .Fn read "int d" "void *buf" "size_t nbytes"
 .Ft ssize_t
+.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
 .Fn readv "int d" "const struct iovec *iov" "int iovcnt"
 .Ft ssize_t
-.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.Fn preadv "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
 .Sh DESCRIPTION
 The
 .Fn read
@@ -73,12 +76,16 @@
 array: iov[0], iov[1], ..., iov[iovcnt\|\-\|1].
 The
 .Fn pread
-system call
-performs the same function, but reads from the specified position in
+and
+.Fn preadv
+system calls
+perform the same functions, but read from the specified position in
 the file without modifying the file pointer.
 .Pp
 For
-.Fn readv ,
+.Fn readv
+and
+.Fn preadv ,
 the
 .Fa iovec
 structure is defined as:
@@ -119,8 +126,9 @@
 Upon successful completion,
 .Fn read ,
 .Fn readv ,
-and
 .Fn pread
+and
+.Fn preadv
 return the number of bytes actually read and placed in the buffer.
 The system guarantees to read the number of bytes requested if
 the descriptor references a normal file that has that many bytes left
@@ -137,8 +145,9 @@
 The
 .Fn read ,
 .Fn readv ,
-and
 .Fn pread
+and
+.Fn preadv
 system calls
 will succeed unless:
 .Bl -tag -width Er
@@ -189,6 +198,8 @@
 .Pp
 In addition,
 .Fn readv
+and
+.Fn preadv
 may return one of the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
@@ -217,7 +228,9 @@
 .Pp
 The
 .Fn pread
-system call may also return the following errors:
+and
+.Fn preadv
+system calls may also return the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The
@@ -249,6 +262,10 @@
 system calls are expected to conform to
 .St -xpg4.2 .
 .Sh HISTORY
+The
+.Fn preadv
+system call appeared in
+.Fx 5.4 .
 The
 .Fn pread
 function appeared in
--- /usr/src/lib/libc/sys/write.2	Tue Apr 26 12:15:43 2005
+++ /usr/src/lib/libc/sys/write.2	Tue Apr 26 12:30:34 2005
@@ -50,9 +50,11 @@
 .Ft ssize_t
 .Fn write "int d" "const void *buf" "size_t nbytes"
 .Ft ssize_t
+.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Ft ssize_t
 .Fn writev "int d" "const struct iovec *iov" "int iovcnt"
 .Ft ssize_t
-.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.Fn pwritev "int d" "const struct iovec *iov" "int iovcnt" "off_t offset"
 .Sh DESCRIPTION
 The
 .Fn write
@@ -74,12 +76,16 @@
 array: iov[0], iov[1], ..., iov[iovcnt\|-\|1].
 The
 .Fn pwrite
-system call
-performs the same function, but writes to the specified position in
+and
+.Fn pwritev
+system calls
+perform the same functions, but write to the specified position in
 the file without modifying the file pointer.
 .Pp
 For
-.Fn writev ,
+.Fn writev
+and
+.Fn pwritev,
 the
 .Fa iovec
 structure is defined as:
@@ -144,8 +150,9 @@
 The
 .Fn write ,
 .Fn writev ,
-and
 .Fn pwrite
+and
+.Fn pwritev
 system calls
 will fail and the file pointer will remain unchanged if:
 .Bl -tag -width Er
@@ -202,6 +209,8 @@
 .Pp
 In addition,
 .Fn writev
+and
+.Fn pwritev
 may return one of the following errors:
 .Bl -tag -width Er
 .It Bq Er EDESTADDRREQ
@@ -234,7 +243,9 @@
 .Pp
 The
 .Fn pwrite
-system call may also return the following errors:
+and
+.Fn pwritev
+system calls may also return the following errors:
 .Bl -tag -width Er
 .It Bq Er EINVAL
 The
@@ -261,6 +272,10 @@
 system calls are expected to conform to
 .St -xpg4.2 .
 .Sh HISTORY
+The
+.Fn pwritev
+system call appeared in
+.Fx 5.4 .
 The
 .Fn pwrite
 function appeared in
--- /usr/src/sys/sys/syscallsubr.h	Tue Apr 26 13:22:49 2005
+++ /usr/src/sys/sys/syscallsubr.h	Tue Apr 26 13:22:27 2005
@@ -96,8 +96,12 @@
 	    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 flags);
 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 flags);
 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);
--- /usr/src/sys/sys/uio.h	Fri Jan  7 03:29:24 2005
+++ /usr/src/sys/sys/uio.h	Tue Apr 26 12:14:46 2005
@@ -101,6 +101,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 */
--- /usr/src/sys/kern/syscalls.master	Sat Apr 23 04:36:07 2005
+++ /usr/src/sys/kern/syscalls.master	Tue Apr 26 12:14:46 2005
@@ -411,8 +411,11 @@
 286	UNIMPL	nosys
 287	UNIMPL	nosys
 288	UNIMPL	nosys
-289	UNIMPL	nosys
-290	UNIMPL	nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289	MSTD	{ ssize_t preadv(int fd, struct iovec *iovp, u_int iovcnt,\
+		    off_t offset); }
+290	MSTD	{ ssize_t pwritev(int fd, struct iovec *iovp, u_int iovcnt,\
+		    off_t offset); }
 291	UNIMPL	nosys
 292	UNIMPL	nosys
 293	UNIMPL	nosys
--- /usr/src/sys/kern/sys_generic.c	Fri Apr  1 00:51:18 2005
+++ /usr/src/sys/kern/sys_generic.c	Tue Apr 26 13:21:15 2005
@@ -233,9 +233,47 @@
 	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, FOF_OFFSET);
+	free(auio, M_IOV);
+	return (error);
+}
+
 int
 kern_readv(struct thread *td, int fd, struct uio *auio)
 {
+	return (kern_preadv(td, fd, auio, (off_t)-1, 0));
+}
+
+int
+kern_preadv(td, fd, auio, offset, flags)
+	struct thread *td;
+	struct uio *auio;
+	int fd, flags;
+	off_t offset;
+{
 	struct file *fp;
 	long cnt;
 	int error;
@@ -253,13 +291,14 @@
 		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;
@@ -430,9 +469,47 @@
 	return (error);
 }
 
+/*
+ * Gather posiotioned 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, FOF_OFFSET);
+	free(auio, M_IOV);
+	return (error);
+}
+
 int
 kern_writev(struct thread *td, int fd, struct uio *auio)
 {
+	return (kern_pwritev(td, fd, auio, (off_t)-1 , 0));
+}
+
+int
+kern_pwritev(td, fd, auio, offset, flags)
+	struct thread *td;
+	struct uio *auio;
+	int fd, flags;
+	off_t offset;
+{
 	struct file *fp;
 	long cnt;
 	int error;
@@ -445,6 +522,7 @@
 		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,7 +530,7 @@
 	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;
--- /usr/src/sys/compat/freebsd32/syscalls.master	Tue Mar  1 07:32:53 2005
+++ /usr/src/sys/compat/freebsd32/syscalls.master	Tue Apr 26 13:52:24 2005
@@ -406,8 +406,13 @@
 286	UNIMPL	nosys
 287	UNIMPL	nosys
 288	UNIMPL	nosys
-289	UNIMPL	nosys
-290	UNIMPL	nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289	STD { ssize_t freebsd32_preadv(int fd, struct iovec32 *iovp,\
+		    u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
+290	STD { ssize_t freebsd32_pwritev(int fd, struct iovec32 *iovp,\
+		    u_int iovcnt, off_t offset); }
+; XXX note - bigendian is different
 291	UNIMPL	nosys
 292	UNIMPL	nosys
 293	UNIMPL	nosys
--- /usr/src/sys/compat/freebsd32/freebsd32_misc.c	Tue Apr 26 13:14:09 2005
+++ /usr/src/sys/compat/freebsd32/freebsd32_misc.c	Tue Apr 26 13:32:54 2005
@@ -733,7 +733,7 @@
 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
 	if (error)
 		return (error);
-	error = kern_readv(td, uap->fd, auio);
+	error = kern_preadv(td, uap->fd, auio, (off_t)-1 , 0);
 	free(auio, M_IOV);
 	return (error);
 }
@@ -747,7 +747,35 @@
 	error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
 	if (error)
 		return (error);
-	error = kern_writev(td, uap->fd, auio);
+	error = kern_pwritev(td, uap->fd, auio,  (off_t)-1 , 0);
+	free(auio, M_IOV);
+	return (error);
+}
+
+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, FOF_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, FOF_OFFSET);
 	free(auio, M_IOV);
 	return (error);
 }
>Release-Note:
>Audit-Trail:

From: Marc Olzheim <marcolz@stack.nl>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/80362: [PATCH] add preadv() and pwritev() system calls
Date: Wed, 27 Apr 2005 12:08:00 +0200

 New patches are at
 
 http://www.stack.nl/~marcolz/FreeBSD/preadv.current.patch.txt
 
 and
 
 http://www.stack.nl/~marcolz/FreeBSD/preadv.stable.patch.txt
 
 Marc

From: Marc Olzheim <marcolz@stack.nl>
To: David Schultz <das@freebsd.org>, bug-followup@FreeBSD.org
Cc: freebsd-current@freebsd.org
Subject: Re: kern/80362: [PATCH] add preadv() and pwritev() system calls
Date: Mon, 27 Jun 2005 16:07:23 +0200

 Updated the patches again:
 
 http://www.stack.nl/~marcolz/FreeBSD/preadv.current.20050627.patch.txt
 
 After patching, type 'make syscalls.c' in /usr/src/sys/kern and
 'make sysent' in /usr/src/sys/compat/freebsd32/
 
 Could someone please take a look at it / commit it ?
 Or do you want me to put the files generated by the two 'make's into the
 patch as well ?
 I figured it would be better not to, since they are generated anyway...
 
 Marc

From: John Baldwin <jhb@FreeBSD.org>
To: bug-followup@FreeBSD.org,
 marcolz@stack.nl
Cc: sobomax@FreeBSD.org
Subject: Re: kern/80362: [PATCH] add preadv() and pwritev() system calls
Date: Tue, 5 Jul 2005 15:09:42 -0400

 I've looked at this patch and have integrated into a test tree in P4 and 
 played with it some.  The original patch didn't do any of the extra checks 
 that pread() and pwrite() do compared to read() and write() in the preadv() 
 and pwritev() functions (i.e. don't allow the operation on pipes and don't 
 allow negative offsets on devices in /dev).  It also exposed some 
 implementation details in the kern_p{read,write}v() interface (FOF_OFFSET 
 flag) that normally should be hidden from the ABIs.  Instead, I merged much 
 of the common code in dofile{read,write}() and the old kern_{read,write}v() 
 such that read() and write() just construct a uio and call kern_readv() and 
 kern_writev(), respectively.  I then moved the extra p* checks into the 
 kern_preadv() and kern_pwritev() functions and made pread() and pwritev() 
 construct a simple uio and call the kern_foov() cousin as well.  kern_foov() 
 now no longer calls kern_pfoov() but instead, both are simpler wrappers 
 around dofilefoo().  Also, the kern_pfoov() interface is simpler in that it 
 just takes arguments normally passed to the associated syscall.  I didn't 
 change any of the docs for this, just the kernel side.  The updated kernel 
 patch is at http://www.FreeBSD.org/~jhb/patches/preadv.patch
 
 Marc, can you test it to make sure nothing was broken by all the reshuffling?
 
 -- 
 John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
 "Power Users Use the Power to Serve"  =  http://www.FreeBSD.org
State-Changed-From-To: open->patched 
State-Changed-By: jhb 
State-Changed-When: Thu Jul 7 18:20:44 GMT 2005 
State-Changed-Why:  
Will MFC in a week or so. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80362 

From: Marc Olzheim <marcolz@stack.nl>
To: bug-followup@FreeBSD.org, John Baldwin <jhb@FreeBSD.org>
Cc: sobomax@FreeBSD.org, Marc Olzheim <marcolz@stack.nl>
Subject: Re: kern/80362: [PATCH] add preadv() and pwritev() system calls
Date: Thu, 22 Sep 2005 11:55:19 +0200

 Unless this is going to be merged to RELENG_4 as well (I initially built
 it on RELENG_4, but don't have problems keeping the patch in my local
 source tree), I'd say let's close this PR... :-)
 
 Marc
State-Changed-From-To: patched->closed 
State-Changed-By: jhb 
State-Changed-When: Thu Sep 22 18:19:24 GMT 2005 
State-Changed-Why:  
Requested by submitter. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=80362 

From: John Baldwin <jhb@FreeBSD.org>
To: Marc Olzheim <marcolz@stack.nl>
Cc: bug-followup@FreeBSD.org,
 sobomax@FreeBSD.org
Subject: Re: kern/80362: [PATCH] add preadv() and pwritev() system calls
Date: Thu, 22 Sep 2005 14:22:28 -0400

 On Thursday 22 September 2005 05:55 am, Marc Olzheim wrote:
 > Unless this is going to be merged to RELENG_4 as well (I initially built
 > it on RELENG_4, but don't have problems keeping the patch in my local
 > source tree), I'd say let's close this PR... :-)
 
 Ok.  Did I put it in 5?
 
 -- 
 John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
 "Power Users Use the Power to Serve"  =  http://www.FreeBSD.org
>Unformatted:
