summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-09-26 06:54:32 +0000
committerdillon <dillon@FreeBSD.org>2001-09-26 06:54:32 +0000
commit9ab85c59297c02e5c30289d283cdd33f73017e7a (patch)
treec88bd0c3ce1a18ffc92eb369690f7bc61a2f3fb6 /sys/kern
parent8196536441794b09959c5c5d8d292db66f6e64f1 (diff)
downloadFreeBSD-src-9ab85c59297c02e5c30289d283cdd33f73017e7a.zip
FreeBSD-src-9ab85c59297c02e5c30289d283cdd33f73017e7a.tar.gz
Make uio_yield() a global. Call uio_yield() between chunks
in vn_rdwr_inchunks(), allowing other processes to gain an exclusive lock on the vnode. Specifically: directory scanning, to avoid a race to the root directory, and multiple child processes coring simultaniously so they can figure out that some other core'ing child has an exclusive adv lock and just exit instead. This completely fixes performance problems when large programs core. You can have hundreds of copies (forked children) of the same binary core all at once and not notice. MFC after: 3 days
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/imgact_aout.c4
-rw-r--r--sys/kern/imgact_elf.c4
-rw-r--r--sys/kern/kern_subr.c4
-rw-r--r--sys/kern/vfs_vnops.c5
4 files changed, 9 insertions, 8 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 3ec8f5f..5a53581 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -269,14 +269,14 @@ aout_coredump(td, vp, limit)
error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
(int)ctob(vm->vm_dsize),
(off_t)ctob(UAREA_PAGES + KSTACK_PAGES), UIO_USERSPACE,
- IO_UNIT, cred, (int *) NULL, td);
+ IO_UNIT | IO_DIRECT, cred, (int *) NULL, td);
if (error == 0)
error = vn_rdwr_inchunks(UIO_WRITE, vp,
(caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
round_page(ctob(vm->vm_ssize)),
(off_t)ctob(UAREA_PAGES + KSTACK_PAGES) +
ctob(vm->vm_dsize), UIO_USERSPACE,
- IO_UNIT, cred, (int *) NULL, td);
+ IO_UNIT | IO_DIRECT, cred, (int *) NULL, td);
return (error);
}
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 66a3a34..d7a27ba 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -802,7 +802,7 @@ elf_coredump(td, vp, limit)
error = vn_rdwr_inchunks(UIO_WRITE, vp,
(caddr_t)php->p_vaddr,
php->p_filesz, offset, UIO_USERSPACE,
- IO_UNIT, cred, (int *)NULL, curthread); /* XXXKSE */
+ IO_UNIT | IO_DIRECT, cred, (int *)NULL, curthread); /* XXXKSE */
if (error != 0)
break;
offset += php->p_filesz;
@@ -966,7 +966,7 @@ elf_corehdr(td, vp, cred, numsegs, hdr, hdrsize)
/* Write it to the core file. */
return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
- UIO_SYSSPACE, IO_UNIT, cred, NULL, td); /* XXXKSE */
+ UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, td); /* XXXKSE */
}
static void
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index 9f53d2d..cab78c2 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -55,8 +55,6 @@
#include <vm/vm_page.h>
#include <vm/vm_map.h>
-static void uio_yield __P((void));
-
SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV,
"Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)");
@@ -381,7 +379,7 @@ phashinit(elements, type, nentries)
return (hashtbl);
}
-static void
+void
uio_yield()
{
struct thread *td;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index b3160b1..2a2bd83 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -338,7 +338,9 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
* Package up an I/O request on a vnode into a uio and do it. The I/O
* request is split up into smaller chunks and we try to avoid saturating
* the buffer cache while potentially holding a vnode locked, so we
- * check bwillwrite() before calling vn_rdwr()
+ * check bwillwrite() before calling vn_rdwr(). We also call uio_yield()
+ * to give other processes a chance to lock the vnode (either other processes
+ * core'ing the same binary, or unrelated processes scanning the directory).
*/
int
vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
@@ -367,6 +369,7 @@ vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
break;
offset += chunk;
base += chunk;
+ uio_yield();
} while (len);
if (aresid)
*aresid += len;
OpenPOWER on IntegriCloud