kern/80362: [PATCH] add preadv() and pwritev() system calls

Marc Olzheim marcolz at stack.nl
Tue Apr 26 06:20:37 PDT 2005


>Number:         80362
>Category:       kern
>Synopsis:       [PATCH] add preadv() and pwritev() system calls
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 26 13:20:30 GMT 2005
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:


More information about the freebsd-bugs mailing list