summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2013-02-24 16:50:53 +0000
committerattilio <attilio@FreeBSD.org>2013-02-24 16:50:53 +0000
commitcff31deb1a197b29ab976c135fdd01dfb6951a6a (patch)
treedbdcb15ce3419e48e823390b612d613ff00bd567 /sys/kern
parentb4e24f9126f7a4c80ce0c44f6b4230021089bc1e (diff)
parent084e5da56e3c4bc6f9c6ed314310a9b8af2c695b (diff)
downloadFreeBSD-src-cff31deb1a197b29ab976c135fdd01dfb6951a6a.zip
FreeBSD-src-cff31deb1a197b29ab976c135fdd01dfb6951a6a.tar.gz
MFC
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c6
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_sig.c23
-rw-r--r--sys/kern/kern_tc.c57
-rw-r--r--sys/kern/kern_thread.c4
-rw-r--r--sys/kern/subr_trap.c2
-rw-r--r--sys/kern/subr_turnstile.c7
-rw-r--r--sys/kern/sys_capability.c2
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/vfs_bio.c42
-rw-r--r--sys/kern/vfs_cluster.c12
-rw-r--r--sys/kern/vfs_export.c1
-rw-r--r--sys/kern/vfs_init.c8
-rw-r--r--sys/kern/vfs_lookup.c2
-rw-r--r--sys/kern/vfs_syscalls.c19
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, &notbufdflashes, 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;
OpenPOWER on IntegriCloud