diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2001-03-08 16:28:10 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2001-03-08 16:28:10 +0000 |
commit | fb925d8493457c06e0ec9cf4781746978ad8aa3d (patch) | |
tree | 089d7b025f12611737515053878bfaf626ab1b1a | |
parent | 5644834a335f630c4a5ebfe947ff55225b8d9ebc (diff) | |
download | FreeBSD-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.c | 27 |
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; } /* |