Author: kib Date: Sat Oct 4 18:35:00 2014 New Revision: 272535 URL: https://svnweb.freebsd.org/changeset/base/272535
Log: Fixes for i/o during coredumping: - Do not dump into system files. - Do not acquire write reference to the mount point where img.core is written, in the coredump(). The vn_rdwr() calls from ELF imgact request the write ref from vn_rdwr(). Recursive acqusition of the write ref deadlocks with the unmount. - Instead, take the range lock for the whole core file. This prevents parallel dumping from two processes executing the same image, converting the useless interleaved dump into sequential dumping, with second core overwriting the first. Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Modified: head/sys/kern/imgact_elf.c head/sys/kern/kern_sig.c Modified: head/sys/kern/imgact_elf.c ============================================================================== --- head/sys/kern/imgact_elf.c Sat Oct 4 18:28:27 2014 (r272534) +++ head/sys/kern/imgact_elf.c Sat Oct 4 18:35:00 2014 (r272535) @@ -1112,8 +1112,8 @@ core_output(struct vnode *vp, void *base #endif } else { error = vn_rdwr_inchunks(UIO_WRITE, vp, base, len, offset, - UIO_USERSPACE, IO_UNIT | IO_DIRECT, active_cred, file_cred, - NULL, td); + UIO_USERSPACE, IO_UNIT | IO_DIRECT | IO_RANGELOCKED, + active_cred, file_cred, NULL, td); } return (error); } @@ -1160,8 +1160,8 @@ sbuf_drain_core_output(void *arg, const #endif error = vn_rdwr_inchunks(UIO_WRITE, p->vp, __DECONST(void *, data), len, p->offset, UIO_SYSSPACE, - IO_UNIT | IO_DIRECT, p->active_cred, p->file_cred, NULL, - p->td); + IO_UNIT | IO_DIRECT | IO_RANGELOCKED, p->active_cred, + p->file_cred, NULL, p->td); if (locked) PROC_LOCK(p->td->td_proc); if (error != 0) Modified: head/sys/kern/kern_sig.c ============================================================================== --- head/sys/kern/kern_sig.c Sat Oct 4 18:28:27 2014 (r272534) +++ head/sys/kern/kern_sig.c Sat Oct 4 18:35:00 2014 (r272535) @@ -3214,8 +3214,8 @@ coredump(struct thread *td) struct flock lf; struct vattr vattr; int error, error1, locked; - struct mount *mp; char *name; /* name of corefile */ + void *rl_cookie; off_t limit; int compress; @@ -3248,39 +3248,33 @@ coredump(struct thread *td) } PROC_UNLOCK(p); -restart: error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, compress, &vp, &name); if (error != 0) return (error); - /* Don't dump to non-regular files or files with links. */ + /* + * Don't dump to non-regular files or files with links. + * Do not dump into system files. + */ if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 || - vattr.va_nlink != 1) { + vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0) { VOP_UNLOCK(vp, 0); error = EFAULT; goto close; } VOP_UNLOCK(vp, 0); + + /* Postpone other writers, including core dumps of other processes. */ + rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX); + lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; lf.l_type = F_WRLCK; locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0); - if (vn_start_write(vp, &mp, V_NOWAIT) != 0) { - lf.l_type = F_UNLCK; - if (locked) - VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); - if ((error = vn_close(vp, FWRITE, cred, td)) != 0) - goto out; - if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) - goto out; - free(name, M_TEMP); - goto restart; - } - VATTR_NULL(&vattr); vattr.va_size = 0; if (set_core_nodump_flag) @@ -3288,7 +3282,6 @@ restart: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); VOP_SETATTR(vp, &vattr, cred); VOP_UNLOCK(vp, 0); - vn_finished_write(mp); PROC_LOCK(p); p->p_acflag |= ACORE; PROC_UNLOCK(p); @@ -3304,11 +3297,11 @@ restart: lf.l_type = F_UNLCK; VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK); } + vn_rangelock_unlock(vp, rl_cookie); close: error1 = vn_close(vp, FWRITE, cred, td); if (error == 0) error = error1; -out: #ifdef AUDIT audit_proc_coredump(td, name, error); #endif _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"