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"

Reply via email to