From 3418ebebfe36e7bcaf380fd3a462b77b59adf1f9 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 26 Sep 2001 06:54:32 +0000 Subject: [PATCH] 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 --- sys/kern/imgact_aout.c | 4 ++-- sys/kern/imgact_elf.c | 4 ++-- sys/kern/kern_subr.c | 4 +--- sys/kern/vfs_vnops.c | 5 ++++- sys/sys/uio.h | 1 + 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 3ec8f5fbc8de..5a5358193fb4 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 66a3a3481be2..d7a27baaf500 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 9f53d2d1f00e..cab78c2015ca 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -55,8 +55,6 @@ #include #include -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 b3160b1d9600..2a2bd8308891 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; diff --git a/sys/sys/uio.h b/sys/sys/uio.h index 48f6c97bce26..eec95a285ef3 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -84,6 +84,7 @@ struct uio { struct vm_object; +void uio_yield __P((void)); int uiomove __P((caddr_t, int, struct uio *)); int uiomoveco __P((caddr_t, int, struct uio *, struct vm_object *)); int uioread __P((int, struct uio *, struct vm_object *, int *));