Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Oct 2014 18:35:00 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r272535 - head/sys/kern
Message-ID:  <201410041835.s94IZ1Pd004053@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410041835.s94IZ1Pd004053>