diff options
author | dillon <dillon@FreeBSD.org> | 2001-09-08 20:02:33 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2001-09-08 20:02:33 +0000 |
commit | d73b3c59f0f82580650e5b2965bdd3dd4cac7bd5 (patch) | |
tree | 5f36b4fb47a0f9f3d486afb708c5f95a6d1f5472 /sys/kern/kern_sig.c | |
parent | df61d9eb64550a7afc1b41ccc9e0261af45c98c1 (diff) | |
download | FreeBSD-src-d73b3c59f0f82580650e5b2965bdd3dd4cac7bd5.zip FreeBSD-src-d73b3c59f0f82580650e5b2965bdd3dd4cac7bd5.tar.gz |
This brings in a Yahoo coredump patch from Paul, with additional mods by
me (addition of vn_rdwr_inchunks). The problem Yahoo is solving is that
if you have large process images core dumping, or you have a large number of
forked processes all core dumping at the same time, the original coredump code
would leave the vnode locked throughout. This can cause the directory vnode
to get locked up, which can cause the parent directory vnode to get locked
up, and so on all the way to the root node, locking the entire machine up
for extremely long periods of time.
This patch solves the problem in two ways. First it uses an advisory
non-blocking lock to abort multiple processes trying to core to the same
file. Second (my contribution) it chunks up the writes and uses bwillwrite()
to avoid holding the vnode locked while blocking in the buffer cache.
Submitted by: ps
Reviewed by: dillon
MFC after: 2 weeks
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r-- | sys/kern/kern_sig.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index c64af8f..607c78c 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -68,6 +68,7 @@ #include <sys/sysent.h> #include <sys/sysctl.h> #include <sys/malloc.h> +#include <sys/unistd.h> #include <machine/cpu.h> @@ -1853,6 +1854,7 @@ coredump(p) { register struct vnode *vp; register struct ucred *cred = p->p_ucred; + struct flock lf; struct nameidata nd; struct vattr vattr; int error, error1, flags; @@ -1895,8 +1897,19 @@ restart: return (error); NDFREE(&nd, NDF_ONLY_PNBUF); vp = nd.ni_vp; + + VOP_UNLOCK(vp, 0, p); + lf.l_whence = SEEK_SET; + lf.l_start = 0; + lf.l_len = 0; + lf.l_type = F_WRLCK; + error = VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK); + if (error) + goto out2; + if (vn_start_write(vp, &mp, V_NOWAIT) != 0) { - VOP_UNLOCK(vp, 0, p); + lf.l_type = F_UNLCK; + VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); if ((error = vn_close(vp, FWRITE, cred, p)) != 0) return (error); if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) @@ -1908,7 +1921,7 @@ restart: if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { error = EFAULT; - goto out; + goto out1; } VATTR_NULL(&vattr); vattr.va_size = 0; @@ -1922,9 +1935,11 @@ restart: p->p_sysent->sv_coredump(p, vp, limit) : ENOSYS; -out: - VOP_UNLOCK(vp, 0, p); +out1: + lf.l_type = F_UNLCK; + VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); vn_finished_write(mp); +out2: error1 = vn_close(vp, FWRITE, cred, p); if (error == 0) error = error1; |