diff options
author | attilio <attilio@FreeBSD.org> | 2013-02-24 16:50:53 +0000 |
---|---|---|
committer | attilio <attilio@FreeBSD.org> | 2013-02-24 16:50:53 +0000 |
commit | cff31deb1a197b29ab976c135fdd01dfb6951a6a (patch) | |
tree | dbdcb15ce3419e48e823390b612d613ff00bd567 /sys/kern | |
parent | b4e24f9126f7a4c80ce0c44f6b4230021089bc1e (diff) | |
parent | 084e5da56e3c4bc6f9c6ed314310a9b8af2c695b (diff) | |
download | FreeBSD-src-cff31deb1a197b29ab976c135fdd01dfb6951a6a.zip FreeBSD-src-cff31deb1a197b29ab976c135fdd01dfb6951a6a.tar.gz |
MFC
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_descrip.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 23 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 57 | ||||
-rw-r--r-- | sys/kern/kern_thread.c | 4 | ||||
-rw-r--r-- | sys/kern/subr_trap.c | 2 | ||||
-rw-r--r-- | sys/kern/subr_turnstile.c | 7 | ||||
-rw-r--r-- | sys/kern/sys_capability.c | 2 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 42 | ||||
-rw-r--r-- | sys/kern/vfs_cluster.c | 12 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 1 | ||||
-rw-r--r-- | sys/kern/vfs_init.c | 8 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 2 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 19 |
15 files changed, 145 insertions, 44 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index fc74bdb..9de55e82 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1949,11 +1949,11 @@ fdfree(struct thread *td) fdp->fd_jdir = NULL; FILEDESC_XUNLOCK(fdp); - if (cdir) + if (cdir != NULL) vrele(cdir); - if (rdir) + if (rdir != NULL) vrele(rdir); - if (jdir) + if (jdir != NULL) vrele(jdir); fddrop(fdp); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 0d2709f..287d202 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -942,7 +942,7 @@ fail1: vmspace_free(vm2); uma_zfree(proc_zone, newproc); #ifdef PROCDESC - if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL)) { + if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) { fdclose(td->td_proc->p_fd, fp_procdesc, *procdescp, td); fdrop(fp_procdesc, td); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5bb49a8..e1dbedc 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2537,16 +2537,22 @@ tdsigcleanup(struct thread *td) } -/* Defer the delivery of SIGSTOP for the current thread. */ -void -sigdeferstop(struct thread *td) +/* + * Defer the delivery of SIGSTOP for the current thread. Returns true + * if stops were deferred and false if they were already deferred. + */ +int +sigdeferstop(void) { + struct thread *td; - KASSERT(!(td->td_flags & TDF_SBDRY), - ("attempt to set TDF_SBDRY recursively")); + td = curthread; + if (td->td_flags & TDF_SBDRY) + return (0); thread_lock(td); td->td_flags |= TDF_SBDRY; thread_unlock(td); + return (1); } /* @@ -2555,11 +2561,11 @@ sigdeferstop(struct thread *td) * will suspend either via ast() or a subsequent interruptible sleep. */ void -sigallowstop(struct thread *td) +sigallowstop() { + struct thread *td; - KASSERT(td->td_flags & TDF_SBDRY, - ("attempt to clear already-cleared TDF_SBDRY")); + td = curthread; thread_lock(td); td->td_flags &= ~TDF_SBDRY; thread_unlock(td); @@ -3130,6 +3136,7 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, break; default: sbuf_putc(&sb, format[i]); + break; } } free(hostname, M_TEMP); diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 2ffa2f9..6e1f486 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1446,6 +1446,50 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, * RFC 2783 PPS-API implementation. */ +static int +pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) +{ + int err, timo; + pps_seq_t aseq, cseq; + struct timeval tv; + + if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) + return (EINVAL); + + /* + * If no timeout is requested, immediately return whatever values were + * most recently captured. If timeout seconds is -1, that's a request + * to block without a timeout. WITNESS won't let us sleep forever + * without a lock (we really don't need a lock), so just repeatedly + * sleep a long time. + */ + if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) { + if (fapi->timeout.tv_sec == -1) + timo = 0x7fffffff; + else { + tv.tv_sec = fapi->timeout.tv_sec; + tv.tv_usec = fapi->timeout.tv_nsec / 1000; + timo = tvtohz(&tv); + } + aseq = pps->ppsinfo.assert_sequence; + cseq = pps->ppsinfo.clear_sequence; + while (aseq == pps->ppsinfo.assert_sequence && + cseq == pps->ppsinfo.clear_sequence) { + err = tsleep(pps, PCATCH, "ppsfch", timo); + if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) { + continue; + } else if (err != 0) { + return (err); + } + } + } + + pps->ppsinfo.current_mode = pps->ppsparam.mode; + fapi->pps_info_buf = pps->ppsinfo; + + return (0); +} + int pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) { @@ -1485,13 +1529,7 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) return (0); case PPS_IOC_FETCH: fapi = (struct pps_fetch_args *)data; - if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) - return (EINVAL); - if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) - return (EOPNOTSUPP); - pps->ppsinfo.current_mode = pps->ppsparam.mode; - fapi->pps_info_buf = pps->ppsinfo; - return (0); + return (pps_fetch(fapi, pps)); #ifdef FFCLOCK case PPS_IOC_FETCH_FFCOUNTER: fapi_ffc = (struct pps_fetch_ffc_args *)data; @@ -1540,7 +1578,7 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) void pps_init(struct pps_state *pps) { - pps->ppscap |= PPS_TSFMT_TSPEC; + pps->ppscap |= PPS_TSFMT_TSPEC | PPS_CANWAIT; if (pps->ppscap & PPS_CAPTUREASSERT) pps->ppscap |= PPS_OFFSETASSERT; if (pps->ppscap & PPS_CAPTURECLEAR) @@ -1680,6 +1718,9 @@ pps_event(struct pps_state *pps, int event) hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); } #endif + + /* Wakeup anyone sleeping in pps_fetch(). */ + wakeup(pps); } /* diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index bee267f..4f0266b 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -748,10 +748,10 @@ stopme: * P_SINGLE_EXIT | return_instead == 0| return_instead != 0 *---------------+--------------------+--------------------- * 0 | returns 0 | returns 0 or 1 - * | when ST ends | immediatly + * | when ST ends | immediately *---------------+--------------------+--------------------- * 1 | thread exits | returns 1 - * | | immediatly + * | | immediately * 0 = thread_exit() or suspension ok, * other = return error instead of stopping the thread. * diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 22cabcb..bd06f20 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -164,6 +164,8 @@ userret(struct thread *td, struct trapframe *frame) ("userret: Returning with with pinned thread")); KASSERT(td->td_vp_reserv == 0, ("userret: Returning while holding vnode reservation")); + KASSERT((td->td_flags & TDF_SBDRY) == 0, + ("userret: Returning with stop signals deferred")); #ifdef VIMAGE /* Unfortunately td_vnet_lpush needs VNET_DEBUG. */ VNET_ASSERT(curvnet == NULL, diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c index 76fb964..0a21ad9 100644 --- a/sys/kern/subr_turnstile.c +++ b/sys/kern/subr_turnstile.c @@ -215,10 +215,9 @@ propagate_priority(struct thread *td) /* * If the thread is asleep, then we are probably about - * to deadlock. To make debugging this easier, just - * panic and tell the user which thread misbehaved so - * they can hopefully get a stack trace from the truly - * misbehaving thread. + * to deadlock. To make debugging this easier, show + * backtrace of misbehaving thread and panic to not + * leave the kernel deadlocked. */ if (TD_IS_SLEEPING(td)) { printf( diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index fa76356..6fb4fee 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -113,7 +113,7 @@ sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap) { u_int i; - i = (IN_CAPABILITY_MODE(td)) ? 1 : 0; + i = IN_CAPABILITY_MODE(td) ? 1 : 0; return (copyout(&i, uap->modep, sizeof(i))); } diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 338256c..5d0c434 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -473,7 +473,7 @@ sys_pipe(struct thread *td, struct pipe_args *uap) error = kern_pipe(td, fildes); if (error) return (error); - + td->td_retval[0] = fildes[0]; td->td_retval[1] = fildes[1]; diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 96c8442..6393399 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -206,6 +206,9 @@ SYSCTL_INT(_vfs, OID_AUTO, flushbufqtarget, CTLFLAG_RW, &flushbufqtarget, 0, static long notbufdflashes; SYSCTL_LONG(_vfs, OID_AUTO, notbufdflashes, CTLFLAG_RD, ¬bufdflashes, 0, "Number of dirty buffer flushes done by the bufdaemon helpers"); +static long barrierwrites; +SYSCTL_LONG(_vfs, OID_AUTO, barrierwrites, CTLFLAG_RW, &barrierwrites, 0, + "Number of barrier writes"); /* * Wakeup point for bufdaemon, as well as indicator of whether it is already @@ -888,6 +891,9 @@ bufwrite(struct buf *bp) return (0); } + if (bp->b_flags & B_BARRIER) + barrierwrites++; + oldflags = bp->b_flags; BUF_ASSERT_HELD(bp); @@ -1007,6 +1013,8 @@ bdwrite(struct buf *bp) CTR3(KTR_BUF, "bdwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); KASSERT(bp->b_bufobj != NULL, ("No b_bufobj %p", bp)); + KASSERT((bp->b_flags & B_BARRIER) == 0, + ("Barrier request in delayed write %p", bp)); BUF_ASSERT_HELD(bp); if (bp->b_flags & B_INVAL) { @@ -1167,6 +1175,40 @@ bawrite(struct buf *bp) } /* + * babarrierwrite: + * + * Asynchronous barrier write. Start output on a buffer, but do not + * wait for it to complete. Place a write barrier after this write so + * that this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +void +babarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_ASYNC | B_BARRIER; + (void) bwrite(bp); +} + +/* + * bbarrierwrite: + * + * Synchronous barrier write. Start output on a buffer and wait for + * it to complete. Place a write barrier after this write so that + * this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +int +bbarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_BARRIER; + return (bwrite(bp)); +} + +/* * bwillwrite: * * Called prior to the locking of any vnodes when we are expecting to diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 19ee05f..663b66f 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -944,11 +944,17 @@ cluster_wbuild(vp, size, start_lbn, len) } bp->b_bcount += size; bp->b_bufsize += size; - bundirty(tbp); - tbp->b_flags &= ~B_DONE; - tbp->b_ioflags &= ~BIO_ERROR; + /* + * If any of the clustered buffers have their + * B_BARRIER flag set, transfer that request to + * the cluster. + */ + bp->b_flags |= (tbp->b_flags & B_BARRIER); + tbp->b_flags &= ~(B_DONE | B_BARRIER); tbp->b_flags |= B_ASYNC; + tbp->b_ioflags &= ~BIO_ERROR; tbp->b_iocmd = BIO_WRITE; + bundirty(tbp); reassignbuf(tbp); /* put on clean list */ bufobj_wref(tbp->b_bufobj); BUF_KERNPROC(tbp); diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 114c23e..6a3f291 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/refcount.h> +#include <sys/signalvar.h> #include <sys/socket.h> #include <sys/systm.h> #include <sys/vnode.h> diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 8172f18..eab48fb 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -122,7 +122,7 @@ struct vfsconf * vfs_byname_kld(const char *fstype, struct thread *td, int *error) { struct vfsconf *vfsp; - int fileid; + int fileid, loaded; vfsp = vfs_byname(fstype); if (vfsp != NULL) @@ -130,13 +130,17 @@ vfs_byname_kld(const char *fstype, struct thread *td, int *error) /* Try to load the respective module. */ *error = kern_kldload(td, fstype, &fileid); + loaded = (*error == 0); + if (*error == EEXIST) + *error = 0; if (*error) return (NULL); /* Look up again to see if the VFS was loaded. */ vfsp = vfs_byname(fstype); if (vfsp == NULL) { - (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE); + if (loaded) + (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE); *error = ENODEV; return (NULL); } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index e5ee4f6..fbde152 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -339,7 +339,7 @@ namei(struct nameidata *ndp) auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; - auio.uio_td = (struct thread *)0; + auio.uio_td = td; auio.uio_resid = MAXPATHLEN; error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); if (error) { diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index dd1232c..bbda70d 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -980,7 +980,10 @@ flags_to_rights(int flags) if (flags & O_TRUNC) rights |= CAP_FTRUNCATE; - if ((flags & O_EXLOCK) || (flags & O_SHLOCK)) + if (flags & (O_SYNC | O_FSYNC)) + rights |= CAP_FSYNC; + + if (flags & (O_EXLOCK | O_SHLOCK)) rights |= CAP_FLOCK; return (rights); @@ -3265,8 +3268,7 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr, AUDIT_ARG_FD(fd); if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) - != 0) + if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) != 0) return (error); #ifdef AUDIT vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); @@ -3416,8 +3418,7 @@ sys_fsync(td, uap) int error, lock_flags; AUDIT_ARG_FD(uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, - &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, &fp)) != 0) return (error); vp = fp->f_vnode; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) @@ -3526,8 +3527,7 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, goto out1; } NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | - SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE, - td); + SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE, td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -3826,8 +3826,7 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, - &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -4618,7 +4617,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, error = fget(td, fd, 0, &fp); if (error != 0) goto out; - + switch (fp->f_type) { case DTYPE_VNODE: break; |