From b49d824e8bc1df3bef3e72a9f2ddcc59a8b72ef0 Mon Sep 17 00:00:00 2001 From: Mike Silbersack Date: Sun, 8 Feb 2004 07:35:48 +0000 Subject: [PATCH] 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 --- sys/kern/uipc_syscalls.c | 41 +++++++++++++++++++++------------------- sys/sys/socket.h | 5 +++++ 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