summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_cow.c
diff options
context:
space:
mode:
authorgallatin <gallatin@FreeBSD.org>2004-01-17 21:16:51 +0000
committergallatin <gallatin@FreeBSD.org>2004-01-17 21:16:51 +0000
commit13a64c8523fa176dd82213b32a0a0d8d1d3b4639 (patch)
treebe313382e421677f0a495155e1d2f99e2f0991ef /sys/kern/uipc_cow.c
parent9260b63f077d0e6e5f9fd293c74f1eae26c191e3 (diff)
downloadFreeBSD-src-13a64c8523fa176dd82213b32a0a0d8d1d3b4639.zip
FreeBSD-src-13a64c8523fa176dd82213b32a0a0d8d1d3b4639.tar.gz
Handle sf_buf_alloc() returning null. This can happen if the
process takes a signal while waiting for an sf_buf to become available. Reviewed by: alc
Diffstat (limited to 'sys/kern/uipc_cow.c')
-rw-r--r--sys/kern/uipc_cow.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/sys/kern/uipc_cow.c b/sys/kern/uipc_cow.c
index b475eff..ca6b2d8 100644
--- a/sys/kern/uipc_cow.c
+++ b/sys/kern/uipc_cow.c
@@ -60,18 +60,12 @@ __FBSDID("$FreeBSD$");
struct netsend_cow_stats {
int attempted;
int fail_not_mapped;
- int fail_wired;
- int fail_not_anon;
- int fail_pmap_cow;
- int fail_pg_error;
- int fail_kva;
- int free_post_exit;
+ int fail_sf_buf;
int success;
int iodone;
- int freed;
};
-static struct netsend_cow_stats socow_stats = {0,0,0,0,0,0,0,0,0,0,0};
+static struct netsend_cow_stats socow_stats;
static void socow_iodone(void *addr, void *args);
@@ -141,7 +135,22 @@ socow_setup(struct mbuf *m0, struct uio *uio)
* Allocate an sf buf
*/
sf = sf_buf_alloc(pp);
-
+ if (!sf) {
+ vm_page_lock_queues();
+ vm_page_cowclear(pp);
+ vm_page_unwire(pp, 0);
+ /*
+ * Check for the object going away on us. This can
+ * happen since we don't hold a reference to it.
+ * If so, we're responsible for freeing the page.
+ */
+ if (pp->wire_count == 0 && pp->object == NULL)
+ vm_page_free(pp);
+ vm_page_unlock_queues();
+ socow_stats.fail_sf_buf++;
+ splx(s);
+ return(0);
+ }
/*
* attach to mbuf
*/
OpenPOWER on IntegriCloud