summaryrefslogtreecommitdiff
path: root/sys/uvm
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2013-01-15 01:34:28 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2013-01-15 01:34:28 +0000
commit54e04668b72a7e51fa97923d740f133acbd11e9e (patch)
treef8b12c4c9fe63c3fd86f3bf2ac1631e7bb86b6a2 /sys/uvm
parent888aa04d8ccf18050c96bb942d1317bf51df2613 (diff)
Slice & dice coredump write requests into MAXPHYS blocks, and
yield between operations. Re-grab the vnode every operation, so that multiple coredumps can be saved at the same time. ok guenther beck etc
Diffstat (limited to 'sys/uvm')
-rw-r--r--sys/uvm/uvm_unix.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/uvm/uvm_unix.c b/sys/uvm/uvm_unix.c
index f4d4490b853..a94bf92cbf0 100644
--- a/sys/uvm/uvm_unix.c
+++ b/sys/uvm/uvm_unix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_unix.c,v 1.43 2012/03/09 13:01:29 ariane Exp $ */
+/* $OpenBSD: uvm_unix.c,v 1.44 2013/01/15 01:34:27 deraadt Exp $ */
/* $NetBSD: uvm_unix.c,v 1.18 2000/09/13 15:00:25 thorpej Exp $ */
/*
@@ -162,8 +162,8 @@ uvm_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
vm_map_entry_t entry;
vaddr_t start, end, top;
struct coreseg cseg;
- off_t offset;
- int flag, error = 0;
+ off_t offset, coffset;
+ int csize, chunk, flag, error = 0;
offset = chdr->c_hdrsize + chdr->c_seghdrsize + chdr->c_cpusize;
@@ -233,14 +233,29 @@ uvm_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
break;
offset += chdr->c_seghdrsize;
- error = vn_rdwr(UIO_WRITE, vp,
- (caddr_t)(u_long)cseg.c_addr, (int)cseg.c_size,
- offset, UIO_USERSPACE,
- IO_NODELOCKED|IO_UNIT, cred, NULL, p);
- if (error)
- break;
-
+
+ coffset = 0;
+ csize = (int)cseg.c_size;
+ do {
+ /* Rest of the loop sleeps with lock held, so... */
+ yield();
+
+ chunk = MIN(csize, MAXPHYS);
+ error = vn_rdwr(UIO_WRITE, vp,
+ (caddr_t)(u_long)cseg.c_addr + coffset,
+ chunk, offset + coffset, UIO_USERSPACE,
+ IO_UNIT, cred, NULL, p);
+ if (error)
+ return (error);
+
+ coffset += chunk;
+ csize -= chunk;
+ } while (csize > 0);
offset += cseg.c_size;
+
+ /* Discard the memory */
+ uvm_unmap(map, cseg.c_addr, cseg.c_addr + cseg.c_size);
+
chdr->c_nseg++;
}