Merge branch 'linus' into perf/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -162,10 +162,14 @@ static void cpu_map_kthread_stop(struct work_struct *work)
|
||||
static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
struct xdp_frame *xdpf)
|
||||
{
|
||||
unsigned int hard_start_headroom;
|
||||
unsigned int frame_size;
|
||||
void *pkt_data_start;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Part of headroom was reserved to xdpf */
|
||||
hard_start_headroom = sizeof(struct xdp_frame) + xdpf->headroom;
|
||||
|
||||
/* build_skb need to place skb_shared_info after SKB end, and
|
||||
* also want to know the memory "truesize". Thus, need to
|
||||
* know the memory frame size backing xdp_buff.
|
||||
@@ -183,15 +187,15 @@ static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
* is not at a fixed memory location, with mixed length
|
||||
* packets, which is bad for cache-line hotness.
|
||||
*/
|
||||
frame_size = SKB_DATA_ALIGN(xdpf->len + xdpf->headroom) +
|
||||
frame_size = SKB_DATA_ALIGN(xdpf->len + hard_start_headroom) +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
|
||||
pkt_data_start = xdpf->data - xdpf->headroom;
|
||||
pkt_data_start = xdpf->data - hard_start_headroom;
|
||||
skb = build_skb(pkt_data_start, frame_size);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
skb_reserve(skb, xdpf->headroom);
|
||||
skb_reserve(skb, hard_start_headroom);
|
||||
__skb_put(skb, xdpf->len);
|
||||
if (xdpf->metasize)
|
||||
skb_metadata_set(skb, xdpf->metasize);
|
||||
@@ -205,6 +209,9 @@ static struct sk_buff *cpu_map_build_skb(struct bpf_cpu_map_entry *rcpu,
|
||||
* - RX ring dev queue index (skb_record_rx_queue)
|
||||
*/
|
||||
|
||||
/* Allow SKB to reuse area used by xdp_frame */
|
||||
xdp_scrub_frame(xdpf);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
@@ -554,19 +554,6 @@ struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type typ
|
||||
}
|
||||
EXPORT_SYMBOL(bpf_prog_get_type_path);
|
||||
|
||||
static void bpf_evict_inode(struct inode *inode)
|
||||
{
|
||||
enum bpf_type type;
|
||||
|
||||
truncate_inode_pages_final(&inode->i_data);
|
||||
clear_inode(inode);
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
kfree(inode->i_link);
|
||||
if (!bpf_inode_type(inode, &type))
|
||||
bpf_any_put(inode->i_private, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the mount options in /proc/mounts.
|
||||
*/
|
||||
@@ -579,11 +566,28 @@ static int bpf_show_options(struct seq_file *m, struct dentry *root)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bpf_destroy_inode_deferred(struct rcu_head *head)
|
||||
{
|
||||
struct inode *inode = container_of(head, struct inode, i_rcu);
|
||||
enum bpf_type type;
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
kfree(inode->i_link);
|
||||
if (!bpf_inode_type(inode, &type))
|
||||
bpf_any_put(inode->i_private, type);
|
||||
free_inode_nonrcu(inode);
|
||||
}
|
||||
|
||||
static void bpf_destroy_inode(struct inode *inode)
|
||||
{
|
||||
call_rcu(&inode->i_rcu, bpf_destroy_inode_deferred);
|
||||
}
|
||||
|
||||
static const struct super_operations bpf_super_ops = {
|
||||
.statfs = simple_statfs,
|
||||
.drop_inode = generic_delete_inode,
|
||||
.show_options = bpf_show_options,
|
||||
.evict_inode = bpf_evict_inode,
|
||||
.destroy_inode = bpf_destroy_inode,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@@ -1897,8 +1897,9 @@ continue_func:
|
||||
}
|
||||
frame++;
|
||||
if (frame >= MAX_CALL_FRAMES) {
|
||||
WARN_ONCE(1, "verifier bug. Call stack is too deep\n");
|
||||
return -EFAULT;
|
||||
verbose(env, "the call stack of %d frames is too deep !\n",
|
||||
frame);
|
||||
return -E2BIG;
|
||||
}
|
||||
goto process_func;
|
||||
}
|
||||
|
@@ -706,7 +706,7 @@ static struct dma_debug_entry *dma_entry_alloc(void)
|
||||
#ifdef CONFIG_STACKTRACE
|
||||
entry->stacktrace.max_entries = DMA_DEBUG_STACKTRACE_ENTRIES;
|
||||
entry->stacktrace.entries = entry->st_entries;
|
||||
entry->stacktrace.skip = 2;
|
||||
entry->stacktrace.skip = 1;
|
||||
save_stack_trace(&entry->stacktrace);
|
||||
#endif
|
||||
|
||||
|
@@ -2009,8 +2009,8 @@ event_sched_out(struct perf_event *event,
|
||||
event->pmu->del(event, 0);
|
||||
event->oncpu = -1;
|
||||
|
||||
if (event->pending_disable) {
|
||||
event->pending_disable = 0;
|
||||
if (READ_ONCE(event->pending_disable) >= 0) {
|
||||
WRITE_ONCE(event->pending_disable, -1);
|
||||
state = PERF_EVENT_STATE_OFF;
|
||||
}
|
||||
perf_event_set_state(event, state);
|
||||
@@ -2198,7 +2198,8 @@ EXPORT_SYMBOL_GPL(perf_event_disable);
|
||||
|
||||
void perf_event_disable_inatomic(struct perf_event *event)
|
||||
{
|
||||
event->pending_disable = 1;
|
||||
WRITE_ONCE(event->pending_disable, smp_processor_id());
|
||||
/* can fail, see perf_pending_event_disable() */
|
||||
irq_work_queue(&event->pending);
|
||||
}
|
||||
|
||||
@@ -5810,10 +5811,45 @@ void perf_event_wakeup(struct perf_event *event)
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_pending_event_disable(struct perf_event *event)
|
||||
{
|
||||
int cpu = READ_ONCE(event->pending_disable);
|
||||
|
||||
if (cpu < 0)
|
||||
return;
|
||||
|
||||
if (cpu == smp_processor_id()) {
|
||||
WRITE_ONCE(event->pending_disable, -1);
|
||||
perf_event_disable_local(event);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU-A CPU-B
|
||||
*
|
||||
* perf_event_disable_inatomic()
|
||||
* @pending_disable = CPU-A;
|
||||
* irq_work_queue();
|
||||
*
|
||||
* sched-out
|
||||
* @pending_disable = -1;
|
||||
*
|
||||
* sched-in
|
||||
* perf_event_disable_inatomic()
|
||||
* @pending_disable = CPU-B;
|
||||
* irq_work_queue(); // FAILS
|
||||
*
|
||||
* irq_work_run()
|
||||
* perf_pending_event()
|
||||
*
|
||||
* But the event runs on CPU-B and wants disabling there.
|
||||
*/
|
||||
irq_work_queue_on(&event->pending, cpu);
|
||||
}
|
||||
|
||||
static void perf_pending_event(struct irq_work *entry)
|
||||
{
|
||||
struct perf_event *event = container_of(entry,
|
||||
struct perf_event, pending);
|
||||
struct perf_event *event = container_of(entry, struct perf_event, pending);
|
||||
int rctx;
|
||||
|
||||
rctx = perf_swevent_get_recursion_context();
|
||||
@@ -5822,10 +5858,7 @@ static void perf_pending_event(struct irq_work *entry)
|
||||
* and we won't recurse 'further'.
|
||||
*/
|
||||
|
||||
if (event->pending_disable) {
|
||||
event->pending_disable = 0;
|
||||
perf_event_disable_local(event);
|
||||
}
|
||||
perf_pending_event_disable(event);
|
||||
|
||||
if (event->pending_wakeup) {
|
||||
event->pending_wakeup = 0;
|
||||
@@ -10236,6 +10269,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
|
||||
|
||||
|
||||
init_waitqueue_head(&event->waitq);
|
||||
event->pending_disable = -1;
|
||||
init_irq_work(&event->pending, perf_pending_event);
|
||||
|
||||
mutex_init(&event->mmap_mutex);
|
||||
|
@@ -392,7 +392,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
|
||||
* store that will be enabled on successful return
|
||||
*/
|
||||
if (!handle->size) { /* A, matches D */
|
||||
event->pending_disable = 1;
|
||||
event->pending_disable = smp_processor_id();
|
||||
perf_output_wakeup(handle);
|
||||
local_set(&rb->aux_nest, 0);
|
||||
goto err_put;
|
||||
@@ -480,7 +480,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
|
||||
|
||||
if (wakeup) {
|
||||
if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
|
||||
handle->event->pending_disable = 1;
|
||||
handle->event->pending_disable = smp_processor_id();
|
||||
perf_output_wakeup(handle);
|
||||
}
|
||||
|
||||
|
@@ -1449,6 +1449,10 @@ int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, void *vcpu_info)
|
||||
int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)
|
||||
{
|
||||
data = data->parent_data;
|
||||
|
||||
if (data->chip->flags & IRQCHIP_SKIP_SET_WAKE)
|
||||
return 0;
|
||||
|
||||
if (data->chip->irq_set_wake)
|
||||
return data->chip->irq_set_wake(data, on);
|
||||
|
||||
|
@@ -558,6 +558,7 @@ int __init early_irq_init(void)
|
||||
alloc_masks(&desc[i], node);
|
||||
raw_spin_lock_init(&desc[i].lock);
|
||||
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
|
||||
mutex_init(&desc[i].request_mutex);
|
||||
desc_set_defaults(i, &desc[i], node, NULL, NULL);
|
||||
}
|
||||
return arch_early_irq_init();
|
||||
|
@@ -4689,8 +4689,8 @@ static void free_zapped_rcu(struct rcu_head *ch)
|
||||
return;
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
if (!graph_lock())
|
||||
goto out_irq;
|
||||
arch_spin_lock(&lockdep_lock);
|
||||
current->lockdep_recursion = 1;
|
||||
|
||||
/* closed head */
|
||||
pf = delayed_free.pf + (delayed_free.index ^ 1);
|
||||
@@ -4702,8 +4702,8 @@ static void free_zapped_rcu(struct rcu_head *ch)
|
||||
*/
|
||||
call_rcu_zapped(delayed_free.pf + delayed_free.index);
|
||||
|
||||
graph_unlock();
|
||||
out_irq:
|
||||
current->lockdep_recursion = 0;
|
||||
arch_spin_unlock(&lockdep_lock);
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
|
||||
@@ -4744,21 +4744,17 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size)
|
||||
{
|
||||
struct pending_free *pf;
|
||||
unsigned long flags;
|
||||
int locked;
|
||||
|
||||
init_data_structures_once();
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
locked = graph_lock();
|
||||
if (!locked)
|
||||
goto out_irq;
|
||||
|
||||
arch_spin_lock(&lockdep_lock);
|
||||
current->lockdep_recursion = 1;
|
||||
pf = get_pending_free();
|
||||
__lockdep_free_key_range(pf, start, size);
|
||||
call_rcu_zapped(pf);
|
||||
|
||||
graph_unlock();
|
||||
out_irq:
|
||||
current->lockdep_recursion = 0;
|
||||
arch_spin_unlock(&lockdep_lock);
|
||||
raw_local_irq_restore(flags);
|
||||
|
||||
/*
|
||||
@@ -4911,9 +4907,8 @@ void lockdep_unregister_key(struct lock_class_key *key)
|
||||
return;
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
if (!graph_lock())
|
||||
goto out_irq;
|
||||
|
||||
arch_spin_lock(&lockdep_lock);
|
||||
current->lockdep_recursion = 1;
|
||||
pf = get_pending_free();
|
||||
hlist_for_each_entry_rcu(k, hash_head, hash_entry) {
|
||||
if (k == key) {
|
||||
@@ -4925,8 +4920,8 @@ void lockdep_unregister_key(struct lock_class_key *key)
|
||||
WARN_ON_ONCE(!found);
|
||||
__lockdep_free_key_range(pf, key, 1);
|
||||
call_rcu_zapped(pf);
|
||||
graph_unlock();
|
||||
out_irq:
|
||||
current->lockdep_recursion = 0;
|
||||
arch_spin_unlock(&lockdep_lock);
|
||||
raw_local_irq_restore(flags);
|
||||
|
||||
/* Wait until is_dynamic_key() has finished accessing k->hash_entry. */
|
||||
|
@@ -7784,10 +7784,10 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
|
||||
if (cfs_rq->last_h_load_update == now)
|
||||
return;
|
||||
|
||||
cfs_rq->h_load_next = NULL;
|
||||
WRITE_ONCE(cfs_rq->h_load_next, NULL);
|
||||
for_each_sched_entity(se) {
|
||||
cfs_rq = cfs_rq_of(se);
|
||||
cfs_rq->h_load_next = se;
|
||||
WRITE_ONCE(cfs_rq->h_load_next, se);
|
||||
if (cfs_rq->last_h_load_update == now)
|
||||
break;
|
||||
}
|
||||
@@ -7797,7 +7797,7 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
|
||||
cfs_rq->last_h_load_update = now;
|
||||
}
|
||||
|
||||
while ((se = cfs_rq->h_load_next) != NULL) {
|
||||
while ((se = READ_ONCE(cfs_rq->h_load_next)) != NULL) {
|
||||
load = cfs_rq->h_load;
|
||||
load = div64_ul(load * se->avg.load_avg,
|
||||
cfs_rq_load_avg(cfs_rq) + 1);
|
||||
|
@@ -149,7 +149,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)
|
||||
|
||||
sd->nr = syscall_get_nr(task, regs);
|
||||
sd->arch = syscall_get_arch();
|
||||
syscall_get_arguments(task, regs, 0, 6, args);
|
||||
syscall_get_arguments(task, regs, args);
|
||||
sd->args[0] = args[0];
|
||||
sd->args[1] = args[1];
|
||||
sd->args[2] = args[2];
|
||||
|
@@ -3605,16 +3605,11 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
|
||||
if (unlikely(sig != kinfo.si_signo))
|
||||
goto err;
|
||||
|
||||
/* Only allow sending arbitrary signals to yourself. */
|
||||
ret = -EPERM;
|
||||
if ((task_pid(current) != pid) &&
|
||||
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL)) {
|
||||
/* Only allow sending arbitrary signals to yourself. */
|
||||
ret = -EPERM;
|
||||
if (kinfo.si_code != SI_USER)
|
||||
goto err;
|
||||
|
||||
/* Turn this into a regular kill signal. */
|
||||
prepare_kill_siginfo(sig, &kinfo);
|
||||
}
|
||||
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
|
||||
goto err;
|
||||
} else {
|
||||
prepare_kill_siginfo(sig, &kinfo);
|
||||
}
|
||||
|
@@ -128,6 +128,7 @@ static int zero;
|
||||
static int __maybe_unused one = 1;
|
||||
static int __maybe_unused two = 2;
|
||||
static int __maybe_unused four = 4;
|
||||
static unsigned long zero_ul;
|
||||
static unsigned long one_ul = 1;
|
||||
static unsigned long long_max = LONG_MAX;
|
||||
static int one_hundred = 100;
|
||||
@@ -1750,7 +1751,7 @@ static struct ctl_table fs_table[] = {
|
||||
.maxlen = sizeof(files_stat.max_files),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_doulongvec_minmax,
|
||||
.extra1 = &zero,
|
||||
.extra1 = &zero_ul,
|
||||
.extra2 = &long_max,
|
||||
},
|
||||
{
|
||||
|
@@ -594,7 +594,7 @@ static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now)
|
||||
{
|
||||
struct alarm *alarm = &timr->it.alarm.alarmtimer;
|
||||
|
||||
return ktime_sub(now, alarm->node.expires);
|
||||
return ktime_sub(alarm->node.expires, now);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -7041,12 +7041,16 @@ static void buffer_pipe_buf_release(struct pipe_inode_info *pipe,
|
||||
buf->private = 0;
|
||||
}
|
||||
|
||||
static void buffer_pipe_buf_get(struct pipe_inode_info *pipe,
|
||||
static bool buffer_pipe_buf_get(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
struct buffer_ref *ref = (struct buffer_ref *)buf->private;
|
||||
|
||||
if (ref->ref > INT_MAX/2)
|
||||
return false;
|
||||
|
||||
ref->ref++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Pipe buffer operations for a buffer. */
|
||||
|
@@ -314,6 +314,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
|
||||
struct ring_buffer_event *event;
|
||||
struct ring_buffer *buffer;
|
||||
unsigned long irq_flags;
|
||||
unsigned long args[6];
|
||||
int pc;
|
||||
int syscall_nr;
|
||||
int size;
|
||||
@@ -347,7 +348,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
|
||||
|
||||
entry = ring_buffer_event_data(event);
|
||||
entry->nr = syscall_nr;
|
||||
syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args);
|
||||
syscall_get_arguments(current, regs, args);
|
||||
memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args);
|
||||
|
||||
event_trigger_unlock_commit(trace_file, buffer, event, entry,
|
||||
irq_flags, pc);
|
||||
@@ -583,6 +585,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
||||
struct syscall_metadata *sys_data;
|
||||
struct syscall_trace_enter *rec;
|
||||
struct hlist_head *head;
|
||||
unsigned long args[6];
|
||||
bool valid_prog_array;
|
||||
int syscall_nr;
|
||||
int rctx;
|
||||
@@ -613,8 +616,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
|
||||
return;
|
||||
|
||||
rec->nr = syscall_nr;
|
||||
syscall_get_arguments(current, regs, 0, sys_data->nb_args,
|
||||
(unsigned long *)&rec->args);
|
||||
syscall_get_arguments(current, regs, args);
|
||||
memcpy(&rec->args, args, sizeof(unsigned long) * sys_data->nb_args);
|
||||
|
||||
if ((valid_prog_array &&
|
||||
!perf_call_bpf_enter(sys_data->enter_event, regs, sys_data, rec)) ||
|
||||
|
Reference in New Issue
Block a user