diff options
author | Otavio Salvador <otavio@ossystems.com.br> | 2016-10-26 10:28:23 -0200 |
---|---|---|
committer | Otavio Salvador <otavio@ossystems.com.br> | 2016-10-26 10:28:23 -0200 |
commit | d7568534f54f5eb1efa4143ba09a77116f964c80 (patch) | |
tree | f0baf6887b0634658ca57ce2cdfda7b5355a7df7 /kernel | |
parent | 34002442b17af7220fa52b2d153db90685113947 (diff) | |
parent | 9ca365c0c8bdd8552ec064f0e696600cf7ea66dd (diff) |
Merge tag 'v4.1.35' into 4.1-2.0.x-imx
Linux 4.1.35
* tag 'v4.1.35': (98 commits)
Linux 4.1.35
xhci: fix usb2 resume timing and races.
mm: remove gup_flags FOLL_WRITE games from __get_user_pages()
timekeeping: Fix __ktime_get_fast_ns() regression
time: Add cycles to nanoseconds translation
Linux 4.1.34
openrisc: fix the fix of copy_from_user()
avr32: fix 'undefined reference to `___copy_from_user'
fix memory leaks in tracing_buffers_splice_read()
tracing: Move mutex to protect against resetting of seq data
MIPS: SMP: Fix possibility of deadlock when bringing CPUs online
MIPS: Fix pre-r6 emulation FPU initialisation
btrfs: ensure that file descriptor used with subvol ioctls is a dir
fix fault_in_multipages_...() on architectures with no-op access_ok()
ocfs2: fix start offset to ocfs2_zero_range_for_truncate()
fanotify: fix list corruption in fanotify_get_response()
fsnotify: add a way to stop queueing events on group shutdown
autofs: use dentry flags to block walks during expire
autofs races
ocfs2/dlm: fix race between convert and migration
...
Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched/core.c | 22 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 32 | ||||
-rw-r--r-- | kernel/trace/trace.c | 29 |
3 files changed, 64 insertions, 19 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 98e607121d09..6cb5f00696f5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1672,6 +1672,28 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) success = 1; /* we're going to change ->state */ cpu = task_cpu(p); + /* + * Ensure we load p->on_rq _after_ p->state, otherwise it would + * be possible to, falsely, observe p->on_rq == 0 and get stuck + * in smp_cond_load_acquire() below. + * + * sched_ttwu_pending() try_to_wake_up() + * [S] p->on_rq = 1; [L] P->state + * UNLOCK rq->lock -----. + * \ + * +--- RMB + * schedule() / + * LOCK rq->lock -----' + * UNLOCK rq->lock + * + * [task p] + * [S] p->state = UNINTERRUPTIBLE [L] p->on_rq + * + * Pairs with the UNLOCK+LOCK on rq->lock from the + * last wakeup of our task and the schedule that got our task + * current. + */ + smp_rmb(); if (p->on_rq && ttwu_remote(p, wake_flags)) goto stat; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 8fcc801fde15..d9f112bd42a7 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -309,17 +309,34 @@ u32 (*arch_gettimeoffset)(void) = default_arch_gettimeoffset; static inline u32 arch_gettimeoffset(void) { return 0; } #endif +static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr, + cycle_t delta) +{ + s64 nsec; + + nsec = delta * tkr->mult + tkr->xtime_nsec; + nsec >>= tkr->shift; + + /* If arch requires, add in get_arch_timeoffset() */ + return nsec + arch_gettimeoffset(); +} + static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) { cycle_t delta; - s64 nsec; delta = timekeeping_get_delta(tkr); + return timekeeping_delta_to_ns(tkr, delta); +} - nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift; +static inline s64 timekeeping_cycles_to_ns(struct tk_read_base *tkr, + cycle_t cycles) +{ + cycle_t delta; - /* If arch requires, add in get_arch_timeoffset() */ - return nsec + arch_gettimeoffset(); + /* calculate the delta since the last update_wall_time */ + delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask); + return timekeeping_delta_to_ns(tkr, delta); } /** @@ -421,8 +438,11 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf) tkr = tkf->base + (seq & 0x01); now = ktime_to_ns(tkr->base); - now += clocksource_delta(tkr->read(tkr->clock), - tkr->cycle_last, tkr->mask); + now += timekeeping_delta_to_ns(tkr, + clocksource_delta( + tkr->read(tkr->clock), + tkr->cycle_last, + tkr->mask)); } while (read_seqcount_retry(&tkf->seq, seq)); return now; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index de6ea94c41bb..61ea7e8cdde5 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4694,19 +4694,20 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, struct trace_iterator *iter = filp->private_data; ssize_t sret; - /* return any leftover data */ - sret = trace_seq_to_user(&iter->seq, ubuf, cnt); - if (sret != -EBUSY) - return sret; - - trace_seq_init(&iter->seq); - /* * Avoid more than one consumer on a single file descriptor * This is just a matter of traces coherency, the ring buffer itself * is protected. */ mutex_lock(&iter->mutex); + + /* return any leftover data */ + sret = trace_seq_to_user(&iter->seq, ubuf, cnt); + if (sret != -EBUSY) + goto out; + + trace_seq_init(&iter->seq); + if (iter->trace->read) { sret = iter->trace->read(iter, filp, ubuf, cnt, ppos); if (sret) @@ -5731,9 +5732,6 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, return -EBUSY; #endif - if (splice_grow_spd(pipe, &spd)) - return -ENOMEM; - if (*ppos & (PAGE_SIZE - 1)) return -EINVAL; @@ -5743,6 +5741,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, len &= PAGE_MASK; } + if (splice_grow_spd(pipe, &spd)) + return -ENOMEM; + again: trace_access_lock(iter->cpu_file); entries = ring_buffer_entries_cpu(iter->trace_buffer->buffer, iter->cpu_file); @@ -5800,19 +5801,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, /* did we read anything? */ if (!spd.nr_pages) { if (ret) - return ret; + goto out; + ret = -EAGAIN; if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) - return -EAGAIN; + goto out; ret = wait_on_pipe(iter, true); if (ret) - return ret; + goto out; goto again; } ret = splice_to_pipe(pipe, &spd); +out: splice_shrink_spd(&spd); return ret; |