svn commit: r260461 - in head/sys: compat/freebsd32 kern sys

Adrian Chadd adrian at FreeBSD.org
Thu Jan 9 00:11:16 UTC 2014


Author: adrian
Date: Thu Jan  9 00:11:14 2014
New Revision: 260461
URL: http://svnweb.freebsd.org/changeset/base/260461

Log:
  Refactor out the common sendfile code from the do_sendfile() and the
  compat32 sendfile syscall.
  
  Sponsored by:	Netflix, Inc.

Added:
  head/sys/sys/sf_base.h   (contents, props changed)
Modified:
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/kern/uipc_syscalls.c

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Wed Jan  8 23:09:02 2014	(r260460)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Thu Jan  9 00:11:14 2014	(r260461)
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/condvar.h>
 #include <sys/sf_buf.h>
 #include <sys/sf_sync.h>
+#include <sys/sf_base.h>
 
 #ifdef INET
 #include <netinet/in.h>
@@ -1651,8 +1652,6 @@ freebsd32_do_sendfile(struct thread *td,
 	struct sf_hdtr hdtr;
 	struct uio *hdr_uio, *trl_uio;
 	struct iovec32 *iov32;
-	struct file *fp;
-	cap_rights_t rights;
 	off_t offset;
 	int error;
 	off_t sbytes;
@@ -1690,29 +1689,9 @@ freebsd32_do_sendfile(struct thread *td,
 		}
 	}
 
-	AUDIT_ARG_FD(uap->fd);
+	error = _do_sendfile(td, uap->fd, uap->s, uap->flags, compat,
+	    offset, uap->nbytes, &sbytes, hdr_uio, trl_uio);
 
-	if ((error = fget_read(td, uap->fd,
-	    cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) {
-		goto out;
-	}
-
-	/*
-	 * If we need to wait for completion, initialise the sfsync
-	 * state here.
-	 */
-	if (uap->flags & SF_SYNC)
-		sfs = sf_sync_alloc(uap->flags & SF_SYNC);
-
-	error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,
-	    uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0,
-	    sfs, td);
-	if (sfs != NULL) {
-		sf_sync_syscall_wait(sfs);
-		sf_sync_free(sfs);
-	}
-
-	fdrop(fp, td);
 	if (uap->sbytes != NULL)
 		copyout(&sbytes, uap->sbytes, sizeof(off_t));
 

Modified: head/sys/kern/uipc_syscalls.c
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Wed Jan  8 23:09:02 2014	(r260460)
+++ head/sys/kern/uipc_syscalls.c	Thu Jan  9 00:11:14 2014	(r260461)
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rwlock.h>
 #include <sys/sf_buf.h>
 #include <sys/sf_sync.h>
+#include <sys/sf_base.h>
 #include <sys/sysent.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -1988,51 +1989,23 @@ sys_sendfile(struct thread *td, struct s
 	return (do_sendfile(td, uap, 0));
 }
 
-static int
-do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
+int
+_do_sendfile(struct thread *td, int src_fd, int sock_fd, int flags,
+    int compat, off_t offset, size_t nbytes, off_t *sbytes,
+    struct uio *hdr_uio, struct uio *trl_uio)
 {
-	struct sf_hdtr hdtr;
-	struct uio *hdr_uio, *trl_uio;
-	struct file *fp;
 	cap_rights_t rights;
+	struct sendfile_sync *sfs = NULL;
+	struct file *fp;
 	int error;
-	off_t sbytes;
-	struct sendfile_sync *sfs;
 
-	/*
-	 * File offset must be positive.  If it goes beyond EOF
-	 * we send only the header/trailer and no payload data.
-	 */
-	if (uap->offset < 0)
-		return (EINVAL);
-
-	hdr_uio = trl_uio = NULL;
-	sfs = NULL;
-
-	if (uap->hdtr != NULL) {
-		error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
-		if (error != 0)
-			goto out;
-		if (hdtr.headers != NULL) {
-			error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio);
-			if (error != 0)
-				goto out;
-		}
-		if (hdtr.trailers != NULL) {
-			error = copyinuio(hdtr.trailers, hdtr.trl_cnt, &trl_uio);
-			if (error != 0)
-				goto out;
-
-		}
-	}
-
-	AUDIT_ARG_FD(uap->fd);
+	AUDIT_ARG_FD(src_fd);
 
 	/*
 	 * sendfile(2) can start at any offset within a file so we require
 	 * CAP_READ+CAP_SEEK = CAP_PREAD.
 	 */
-	if ((error = fget_read(td, uap->fd,
+	if ((error = fget_read(td, src_fd,
 	    cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) {
 		goto out;
 	}
@@ -2041,11 +2014,11 @@ do_sendfile(struct thread *td, struct se
 	 * If we need to wait for completion, initialise the sfsync
 	 * state here.
 	 */
-	if (uap->flags & SF_SYNC)
-		sfs = sf_sync_alloc(uap->flags & SF_SYNC);
+	if (flags & SF_SYNC)
+		sfs = sf_sync_alloc(flags & SF_SYNC);
 
-	error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
-	    uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0, sfs, td);
+	error = fo_sendfile(fp, sock_fd, hdr_uio, trl_uio, offset,
+	    nbytes, sbytes, flags, compat ? SFK_COMPAT : 0, sfs, td);
 
 	/*
 	 * If appropriate, do the wait and free here.
@@ -2062,6 +2035,46 @@ do_sendfile(struct thread *td, struct se
 	 */
 	fdrop(fp, td);
 
+out:
+	return (error);
+}
+
+static int
+do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
+{
+	struct sf_hdtr hdtr;
+	struct uio *hdr_uio, *trl_uio;
+	int error;
+	off_t sbytes;
+
+	/*
+	 * File offset must be positive.  If it goes beyond EOF
+	 * we send only the header/trailer and no payload data.
+	 */
+	if (uap->offset < 0)
+		return (EINVAL);
+
+	hdr_uio = trl_uio = NULL;
+
+	if (uap->hdtr != NULL) {
+		error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
+		if (error != 0)
+			goto out;
+		if (hdtr.headers != NULL) {
+			error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio);
+			if (error != 0)
+				goto out;
+		}
+		if (hdtr.trailers != NULL) {
+			error = copyinuio(hdtr.trailers, hdtr.trl_cnt, &trl_uio);
+			if (error != 0)
+				goto out;
+		}
+	}
+
+	error = _do_sendfile(td, uap->fd, uap->s, uap->flags, compat,
+	    uap->offset, uap->nbytes, &sbytes, hdr_uio, trl_uio);
+
 	if (uap->sbytes != NULL) {
 		copyout(&sbytes, uap->sbytes, sizeof(off_t));
 	}

Added: head/sys/sys/sf_base.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/sys/sf_base.h	Thu Jan  9 00:11:14 2014	(r260461)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2013 Adrian Chadd <adrian at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_SYS_SF_BASE_H_
+#define	_SYS_SF_BASE_H_
+
+extern	int _do_sendfile(struct thread *, int src_fd, int sock_fd, int flags,
+	    int compat, off_t offset, size_t nbytes, off_t *sbytes,
+	    struct uio *hdr_uio, struct uio *trl_uio);
+
+#endif	/* _SYS_SF_BASE_H_ */


More information about the svn-src-all mailing list