summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_syscalls.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-01-28 17:37:09 +0000
committerkib <kib@FreeBSD.org>2011-01-28 17:37:09 +0000
commit42cc2c0d98d37d8fc24e6f9e3695c2717d7d31a4 (patch)
treeaf6a353e98cb04f1a9578d40119dcc8576527810 /sys/kern/uipc_syscalls.c
parent36a5448bf6a64e2da00f755937e602cb16e10bc5 (diff)
downloadFreeBSD-src-42cc2c0d98d37d8fc24e6f9e3695c2717d7d31a4.zip
FreeBSD-src-42cc2c0d98d37d8fc24e6f9e3695c2717d7d31a4.tar.gz
If more than one thread allocated sf buffers for sendfile(2), and
each of the threads needs more while current pool of the buffers is exhausted, then neither thread can make progress. Switch to nowait allocations after we got first buffer already. Reported by: az Reviewed by: alc (previous version) Tested by: pho MFC after: 1 week
Diffstat (limited to 'sys/kern/uipc_syscalls.c')
-rw-r--r--sys/kern/uipc_syscalls.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 459082b..ce83a93 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -2126,18 +2126,25 @@ retry_space:
}
/*
- * Get a sendfile buf. We usually wait as long
- * as necessary, but this wait can be interrupted.
+ * Get a sendfile buf. When allocating the
+ * first buffer for mbuf chain, we usually
+ * wait as long as necessary, but this wait
+ * can be interrupted. For consequent
+ * buffers, do not sleep, since several
+ * threads might exhaust the buffers and then
+ * deadlock.
*/
- if ((sf = sf_buf_alloc(pg,
- (mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) {
+ sf = sf_buf_alloc(pg, (mnw || m != NULL) ? SFB_NOWAIT :
+ SFB_CATCH);
+ if (sf == NULL) {
mbstat.sf_allocfail++;
vm_page_lock(pg);
vm_page_unwire(pg, 0);
KASSERT(pg->object != NULL,
("kern_sendfile: object disappeared"));
vm_page_unlock(pg);
- error = (mnw ? EAGAIN : EINTR);
+ if (m == NULL)
+ error = (mnw ? EAGAIN : EINTR);
break;
}
OpenPOWER on IntegriCloud