diff options
author | Renato Botelho <renato@netgate.com> | 2016-08-01 12:53:16 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-08-01 12:53:16 -0300 |
commit | 80c20d0bef69a2c543d1bc2dddd2bc34198fec9b (patch) | |
tree | fc6009a2d49da5ab043d4c847a288f71ec6aa731 /sys/kern | |
parent | f235fecdc77c17505022bc5202d74f3d36b33359 (diff) | |
parent | eed7d9e93aec04a3f6a7d157c4cac7452a6c1727 (diff) | |
download | FreeBSD-src-80c20d0bef69a2c543d1bc2dddd2bc34198fec9b.zip FreeBSD-src-80c20d0bef69a2c543d1bc2dddd2bc34198fec9b.tar.gz |
Merge remote-tracking branch 'origin/stable/11' into devel-11
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exec.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_mutex.c | 28 | ||||
-rw-r--r-- | sys/kern/subr_prf.c | 21 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 55 | ||||
-rw-r--r-- | sys/kern/vfs_aio.c | 23 |
5 files changed, 118 insertions, 11 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 844f1ed..6466a3e 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -759,6 +759,8 @@ interpret: if (p->p_flag & P_PPWAIT) { p->p_flag &= ~(P_PPWAIT | P_PPTRACE); cv_broadcast(&p->p_pwait); + /* STOPs are no longer ignored, arrange for AST */ + signotify(td); } /* diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index 012cf7c..453add4 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -281,6 +281,34 @@ __mtx_lock_spin_flags(volatile uintptr_t *c, int opts, const char *file, WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line); } +int +__mtx_trylock_spin_flags(volatile uintptr_t *c, int opts, const char *file, + int line) +{ + struct mtx *m; + + if (SCHEDULER_STOPPED()) + return (1); + + m = mtxlock2mtx(c); + + KASSERT(m->mtx_lock != MTX_DESTROYED, + ("mtx_trylock_spin() of destroyed mutex @ %s:%d", file, line)); + KASSERT(LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin, + ("mtx_trylock_spin() of sleep mutex %s @ %s:%d", + m->lock_object.lo_name, file, line)); + KASSERT((opts & MTX_RECURSE) == 0, + ("mtx_trylock_spin: unsupp. opt MTX_RECURSE on mutex %s @ %s:%d\n", + m->lock_object.lo_name, file, line)); + if (__mtx_trylock_spin(m, curthread, opts, file, line)) { + LOCK_LOG_TRY("LOCK", &m->lock_object, opts, 1, file, line); + WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line); + return (1); + } + LOCK_LOG_TRY("LOCK", &m->lock_object, opts, 0, file, line); + return (0); +} + void __mtx_unlock_spin_flags(volatile uintptr_t *c, int opts, const char *file, int line) diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index 5bcf39b..3784ffd 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -1196,3 +1196,24 @@ sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr, } } +#ifdef _KERNEL +void +counted_warning(unsigned *counter, const char *msg) +{ + struct thread *td; + unsigned c; + + for (;;) { + c = *counter; + if (c == 0) + break; + if (atomic_cmpset_int(counter, c, c - 1)) { + td = curthread; + log(LOG_INFO, "pid %d (%s) %s%s\n", + td->td_proc->p_pid, td->td_name, msg, + c > 1 ? "" : " - not logging anymore"); + break; + } + } +} +#endif diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index eb44087..763ba0d 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -101,17 +101,29 @@ userret(struct thread *td, struct trapframe *frame) td->td_name); KASSERT((p->p_flag & P_WEXIT) == 0, ("Exiting process returns to usermode")); -#if 0 #ifdef DIAGNOSTIC - /* Check that we called signotify() enough. */ - PROC_LOCK(p); - thread_lock(td); - if (SIGPENDING(td) && ((td->td_flags & TDF_NEEDSIGCHK) == 0 || - (td->td_flags & TDF_ASTPENDING) == 0)) - printf("failed to set signal flags properly for ast()\n"); - thread_unlock(td); - PROC_UNLOCK(p); -#endif + /* + * Check that we called signotify() enough. For + * multi-threaded processes, where signal distribution might + * change due to other threads changing sigmask, the check is + * racy and cannot be performed reliably. + * If current process is vfork child, indicated by P_PPWAIT, then + * issignal() ignores stops, so we block the check to avoid + * classifying pending signals. + */ + if (p->p_numthreads == 1) { + PROC_LOCK(p); + thread_lock(td); + if ((p->p_flag & P_PPWAIT) == 0) { + KASSERT(!SIGPENDING(td) || (td->td_flags & + (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == + (TDF_NEEDSIGCHK | TDF_ASTPENDING), + ("failed to set signal flags for ast p %p " + "td %p fl %x", p, td, td->td_flags)); + } + thread_unlock(td); + PROC_UNLOCK(p); + } #endif #ifdef KTRACE KTRUSERRET(td); @@ -265,6 +277,29 @@ ast(struct trapframe *framep) #endif } +#ifdef DIAGNOSTIC + if (p->p_numthreads == 1 && (flags & TDF_NEEDSIGCHK) == 0) { + PROC_LOCK(p); + thread_lock(td); + /* + * Note that TDF_NEEDSIGCHK should be re-read from + * td_flags, since signal might have been delivered + * after we cleared td_flags above. This is one of + * the reason for looping check for AST condition. + * See comment in userret() about P_PPWAIT. + */ + if ((p->p_flag & P_PPWAIT) == 0) { + KASSERT(!SIGPENDING(td) || (td->td_flags & + (TDF_NEEDSIGCHK | TDF_ASTPENDING)) == + (TDF_NEEDSIGCHK | TDF_ASTPENDING), + ("failed2 to set signal flags for ast p %p td %p " + "fl %x %x", p, td, flags, td->td_flags)); + } + thread_unlock(td); + PROC_UNLOCK(p); + } +#endif + /* * Check for signals. Unlocked reads of p_pendingcnt or * p_siglist might cause process-directed signal to be handled diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 3c9aa44..ead5e7c 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/syscall.h> #include <sys/sysent.h> #include <sys/sysctl.h> +#include <sys/syslog.h> #include <sys/sx.h> #include <sys/taskqueue.h> #include <sys/vnode.h> @@ -110,6 +111,11 @@ static int enable_aio_unsafe = 0; SYSCTL_INT(_vfs_aio, OID_AUTO, enable_unsafe, CTLFLAG_RW, &enable_aio_unsafe, 0, "Permit asynchronous IO on all file types, not just known-safe types"); +static unsigned int unsafe_warningcnt = 1; +SYSCTL_UINT(_vfs_aio, OID_AUTO, unsafe_warningcnt, CTLFLAG_RW, + &unsafe_warningcnt, 0, + "Warnings that will be triggered upon failed IO requests on unsafe files"); + static int max_aio_procs = MAX_AIO_PROCS; SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs, CTLFLAG_RW, &max_aio_procs, 0, "Maximum number of kernel processes to use for handling async IO "); @@ -1664,7 +1670,10 @@ aio_queue_file(struct file *fp, struct kaiocb *job) struct aioliojob *lj; struct kaioinfo *ki; struct kaiocb *job2; + struct vnode *vp; + struct mount *mp; int error, opcode; + bool safe; lj = job->lio; ki = job->userproc->p_aioinfo; @@ -1685,8 +1694,20 @@ aio_queue_file(struct file *fp, struct kaiocb *job) goto done; #endif queueit: - if (!enable_aio_unsafe) + safe = false; + if (fp->f_type == DTYPE_VNODE) { + vp = fp->f_vnode; + if (vp->v_type == VREG || vp->v_type == VDIR) { + mp = fp->f_vnode->v_mount; + if (mp == NULL || (mp->mnt_flag & MNT_LOCAL) != 0) + safe = true; + } + } + if (!(safe || enable_aio_unsafe)) { + counted_warning(&unsafe_warningcnt, + "is attempting to use unsafe AIO requests"); return (EOPNOTSUPP); + } if (opcode == LIO_SYNC) { AIO_LOCK(ki); |