diff options
author | Renato Botelho <renato@netgate.com> | 2017-02-09 11:26:48 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2017-02-09 11:26:48 -0200 |
commit | 4a05f5440acda223e6a0ec5157bc32ecc0f09ff9 (patch) | |
tree | 4c2ece480e5d4155ed35bec62996de40eb179f18 /sys/kern | |
parent | 681a482d8fc4bfc14a24f7a9d75cca6337f2a520 (diff) | |
parent | a1e52233c91fd46e666297270ab655f1abff8535 (diff) | |
download | FreeBSD-src-4a05f5440acda223e6a0ec5157bc32ecc0f09ff9.zip FreeBSD-src-4a05f5440acda223e6a0ec5157bc32ecc0f09ff9.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/imgact_elf.c | 33 | ||||
-rw-r--r-- | sys/kern/kern_procctl.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_switch.c | 15 | ||||
-rw-r--r-- | sys/kern/sched_4bsd.c | 4 | ||||
-rw-r--r-- | sys/kern/sched_ule.c | 4 | ||||
-rw-r--r-- | sys/kern/subr_unit.c | 12 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf2.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 4 |
8 files changed, 61 insertions, 15 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 293a65d..bdf709f 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1176,9 +1176,31 @@ core_output(struct vnode *vp, void *base, size_t len, off_t offset, panic("shouldn't be here"); #endif } else { + /* + * EFAULT is a non-fatal error that we can get, for example, + * if the segment is backed by a file but extends beyond its + * end. + */ error = vn_rdwr_inchunks(UIO_WRITE, vp, base, len, offset, UIO_USERSPACE, IO_UNIT | IO_DIRECT, active_cred, file_cred, NULL, td); + if (error == EFAULT) { + log(LOG_WARNING, "Failed to fully fault in a core file " + "segment at VA %p with size 0x%zx to be written at " + "offset 0x%jx for process %s\n", base, len, offset, + curproc->p_comm); + + /* + * Write a "real" zero byte at the end of the target + * region in the case this is the last segment. + * The intermediate space will be implicitly + * zero-filled. + */ + error = vn_rdwr_inchunks(UIO_WRITE, vp, + __DECONST(void *, zero_region), 1, offset + len - 1, + UIO_SYSSPACE, IO_UNIT | IO_DIRECT, active_cred, + file_cred, NULL, td); + } } return (error); } @@ -2309,7 +2331,16 @@ compress_core (gzFile file, char *inbuf, char *dest_buf, unsigned int len, while (len) { if (inbuf != NULL) { chunk_len = (len > CORE_BUF_SIZE) ? CORE_BUF_SIZE : len; - copyin(inbuf, dest_buf, chunk_len); + + /* + * We can get EFAULT error here. In that case zero out + * the current chunk of the segment. + */ + error = copyin(inbuf, dest_buf, chunk_len); + if (error != 0) { + bzero(dest_buf, chunk_len); + error = 0; + } inbuf += chunk_len; } else { chunk_len = len; diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c index e6e432e..4ccf646 100644 --- a/sys/kern/kern_procctl.c +++ b/sys/kern/kern_procctl.c @@ -243,7 +243,7 @@ reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk) return (ECAPMODE); if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG) return (EINVAL); - if ((rk->rk_flags & ~REAPER_KILL_CHILDREN) != 0) + if ((rk->rk_flags & ~(REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) != 0) return (EINVAL); PROC_UNLOCK(p); reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index d0009b1..f58acd5 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -206,7 +206,22 @@ critical_exit(void) if (td->td_critnest == 1) { td->td_critnest = 0; + + /* + * Interrupt handlers execute critical_exit() on + * leave, and td_owepreempt may be left set by an + * interrupt handler only when td_critnest > 0. If we + * are decrementing td_critnest from 1 to 0, read + * td_owepreempt after decrementing, to not miss the + * preempt. Disallow compiler to reorder operations. + */ + __compiler_membar(); if (td->td_owepreempt && !kdb_active) { + /* + * Microoptimization: we committed to switch, + * disable preemption in interrupt handlers + * while spinning for the thread lock. + */ td->td_critnest = 1; thread_lock(td); td->td_critnest--; diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c index db23e1d..7309ae3 100644 --- a/sys/kern/sched_4bsd.c +++ b/sys/kern/sched_4bsd.c @@ -963,8 +963,8 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) sched_load_rem(); td->td_lastcpu = td->td_oncpu; - preempted = !((td->td_flags & TDF_SLICEEND) || - (flags & SWT_RELINQUISH)); + preempted = (td->td_flags & TDF_SLICEEND) == 0 && + (flags & SW_PREEMPT) != 0; td->td_flags &= ~(TDF_NEEDRESCHED | TDF_SLICEEND); td->td_owepreempt = 0; td->td_oncpu = NOCPU; diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index 30aad12..53a46c9 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -1870,8 +1870,8 @@ sched_switch(struct thread *td, struct thread *newtd, int flags) ts->ts_rltick = ticks; td->td_lastcpu = td->td_oncpu; td->td_oncpu = NOCPU; - preempted = !((td->td_flags & TDF_SLICEEND) || - (flags & SWT_RELINQUISH)); + preempted = (td->td_flags & TDF_SLICEEND) == 0 && + (flags & SW_PREEMPT) != 0; td->td_flags &= ~(TDF_NEEDRESCHED | TDF_SLICEEND); td->td_owepreempt = 0; if (!TD_IS_IDLETHREAD(td)) diff --git a/sys/kern/subr_unit.c b/sys/kern/subr_unit.c index 3bf7aaf..d53ec1e 100644 --- a/sys/kern/subr_unit.c +++ b/sys/kern/subr_unit.c @@ -192,7 +192,7 @@ CTASSERT(sizeof(struct unr) == sizeof(struct unrb)); * Consistency check function. * * Checks the internal consistency as well as we can. - * + * * Called at all boundaries of this API. */ static void @@ -220,7 +220,7 @@ check_unrhdr(struct unrhdr *uh, int line) ("UNR inconsistency: busy %u found %u (line %d)\n", ub->busy, w, line)); y += w; - } else if (up->ptr != NULL) + } else if (up->ptr != NULL) y += up->len; } KASSERT (y == uh->busy, @@ -355,7 +355,7 @@ is_bitmap(struct unrhdr *uh, struct unr *up) /* * Look for sequence of items which can be combined into a bitmap, if * multiple are present, take the one which saves most memory. - * + * * Return (1) if a sequence was found to indicate that another call * might be able to do more. Return (0) if we found no suitable sequence. * @@ -582,7 +582,7 @@ alloc_unrl(struct unrhdr *uh) } /* - * We can always allocate from the first list element, so if we have + * We can always allocate from the first list element, so if we have * nothing on the list, we must have run out of unit numbers. */ if (up == NULL) @@ -797,7 +797,7 @@ free_unrl(struct unrhdr *uh, u_int item, void **p1, void **p2) /* Handle bitmap items */ if (is_bitmap(uh, up)) { ub = up->ptr; - + KASSERT(bit_test(ub->map, item) != 0, ("UNR: Freeing free item %d (bitmap)\n", item)); bit_clear(ub->map, item); @@ -900,7 +900,7 @@ print_unr(struct unrhdr *uh, struct unr *up) for (x = 0; x < up->len; x++) { if (bit_test(ub->map, x)) printf("#"); - else + else printf(" "); } printf("]\n"); diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c index 00472d3..f69b47e 100644 --- a/sys/kern/uipc_mbuf2.c +++ b/sys/kern/uipc_mbuf2.c @@ -161,7 +161,7 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) * the target data is on <n, off>. * if we got enough data on the mbuf "n", we're done. */ - if ((off == 0 || offp) && len <= n->m_len - off && writable) + if ((off == 0 || offp) && len <= n->m_len - off) goto ok; /* diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9f922db..5701e5a 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -464,7 +464,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, nmp = TAILQ_NEXT(mp, mnt_list); continue; } - if (sfsp && count < maxcount) { + if (sfsp != NULL && count < maxcount) { sp = &mp->mnt_stat; /* * Set these in case the underlying filesystem @@ -509,7 +509,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, vfs_unbusy(mp); } mtx_unlock(&mountlist_mtx); - if (sfsp && count > maxcount) + if (sfsp != NULL && count > maxcount) td->td_retval[0] = maxcount; else td->td_retval[0] = count; |