aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Silbersack <silby@FreeBSD.org>2004-02-08 07:35:48 +0000
committerMike Silbersack <silby@FreeBSD.org>2004-02-08 07:35:48 +0000
commitb49d824e8bc1df3bef3e72a9f2ddcc59a8b72ef0 (patch)
treeadace10635c2ee5bfd954e6874ea83f360d8645e
parent08fc808d7fcbf8169e15936893f51d3347f2f9d6 (diff)
downloadsrc-b49d824e8bc1.tar.gz
src-b49d824e8bc1.zip
Add the SF_NODISKIO flag to sendfile. This flag causes sendfile to be
mindful of blocking on disk I/O and instead return EBUSY when such blocking would occur. Results from the DeBox project indicate that blocking on disk I/O can slow the performance of a kqueue/poll based webserver. Using a flag such as SF_NODISKIO and throwing connections that would block to helper processes/threads helped increase performance. Currently, only the Flash webserver uses this flag, although it could probably be applied to thttpd with relative ease. Idea by: Yaoping Ruan & Vivek Pai
Notes
Notes: svn path=/head/; revision=125586
-rw-r--r--sys/kern/uipc_syscalls.c41
-rw-r--r--sys/sys/socket.h5
2 files changed, 27 insertions, 19 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 55f588f20667..28ee96438379 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1836,7 +1836,11 @@ retry_lookup:
* If page is not valid for what we need, initiate I/O
*/
- if (!pg->valid || !vm_page_is_valid(pg, pgoff, xfsize)) {
+ if (pg->valid && vm_page_is_valid(pg, pgoff, xfsize)) {
+ VM_OBJECT_UNLOCK(obj);
+ } else if (uap->flags & SF_NODISKIO) {
+ error = EBUSY;
+ } else {
int bsize, resid;
/*
@@ -1867,26 +1871,25 @@ retry_lookup:
vm_page_lock_queues();
vm_page_flag_clear(pg, PG_ZERO);
vm_page_io_finish(pg);
- 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_busy(pg);
- vm_page_free(pg);
- }
- vm_page_unlock_queues();
- VM_OBJECT_UNLOCK(obj);
- sbunlock(&so->so_snd);
- goto done;
- }
mbstat.sf_iocnt++;
- } else {
+ }
+
+ 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_busy(pg);
+ vm_page_free(pg);
+ }
+ vm_page_unlock_queues();
VM_OBJECT_UNLOCK(obj);
+ sbunlock(&so->so_snd);
+ goto done;
}
vm_page_unlock_queues();
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index 34865fd81a60..4acff20544de 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -505,6 +505,11 @@ struct sf_hdtr {
struct iovec *trailers; /* pointer to an array of trailer struct iovec's */
int trl_cnt; /* number of trailer iovec's */
};
+
+/*
+ * Sendfile-specific flag(s)
+ */
+#define SF_NODISKIO 0x00000001
#endif
#ifndef _KERNEL