summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2001-03-08 16:28:10 +0000
committerdwmalone <dwmalone@FreeBSD.org>2001-03-08 16:28:10 +0000
commitfb925d8493457c06e0ec9cf4781746978ad8aa3d (patch)
tree089d7b025f12611737515053878bfaf626ab1b1a
parent5644834a335f630c4a5ebfe947ff55225b8d9ebc (diff)
downloadFreeBSD-src-fb925d8493457c06e0ec9cf4781746978ad8aa3d.zip
FreeBSD-src-fb925d8493457c06e0ec9cf4781746978ad8aa3d.tar.gz
Make the wait for sendfile buffers interruptable. Stops one process
consuming them all and then getting stuck. Reviewed by: dg Reviewed by: bmilekic Observed by: Andreas Persson <pap@garen.net>
-rw-r--r--sys/kern/uipc_syscalls.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index c46b7ea..d849b21 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1454,11 +1454,17 @@ static struct sf_buf *
sf_buf_alloc()
{
struct sf_buf *sf;
+ int error;
mtx_lock(&sf_freelist.sf_lock);
while ((sf = SLIST_FIRST(&sf_freelist.sf_head)) == NULL) {
sf_buf_alloc_want++;
- msleep(&sf_freelist, &sf_freelist.sf_lock, PVM, "sfbufa", 0);
+ error = msleep(&sf_freelist, &sf_freelist.sf_lock, PVM|PCATCH,
+ "sfbufa", 0);
+ if (error != 0) {
+ sf_buf_alloc_want--;
+ break;
+ }
}
SLIST_REMOVE_HEAD(&sf_freelist.sf_head, free_list);
mtx_unlock(&sf_freelist.sf_lock);
@@ -1707,12 +1713,26 @@ retry_lookup:
}
}
+
+ /*
+ * Get a sendfile buf. We usually wait as long as necessary,
+ * but this wait can be interrupted.
+ */
+ if ((sf = sf_buf_alloc()) == NULL) {
+ s = splvm();
+ vm_page_unwire(pg, 0);
+ if (pg->wire_count == 0 && pg->object == NULL)
+ vm_page_free(pg);
+ splx(s);
+ sbunlock(&so->so_snd);
+ error = EINTR;
+ goto done;
+ }
+
/*
* Allocate a kernel virtual page and insert the physical page
* into it.
*/
-
- sf = sf_buf_alloc();
sf->m = pg;
pmap_qenter(sf->kva, &pg, 1);
/*
@@ -1722,6 +1742,7 @@ retry_lookup:
if (m == NULL) {
error = ENOBUFS;
sf_buf_free((void *)sf->kva, NULL);
+ sbunlock(&so->so_snd);
goto done;
}
/*
OpenPOWER on IntegriCloud