diff options
author | gallatin <gallatin@FreeBSD.org> | 2004-01-17 21:16:51 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2004-01-17 21:16:51 +0000 |
commit | 13a64c8523fa176dd82213b32a0a0d8d1d3b4639 (patch) | |
tree | be313382e421677f0a495155e1d2f99e2f0991ef /sys/kern | |
parent | 9260b63f077d0e6e5f9fd293c74f1eae26c191e3 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/kern/uipc_cow.c | 27 |
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 */ |