Merge tag 'v5.11' into sched/core, to pick up fixes & refresh the branch
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -125,8 +125,12 @@ static int bpf_fd_inode_storage_update_elem(struct bpf_map *map, void *key,
|
||||
|
||||
fd = *(int *)key;
|
||||
f = fget_raw(fd);
|
||||
if (!f || !inode_storage_ptr(f->f_inode))
|
||||
if (!f)
|
||||
return -EBADF;
|
||||
if (!inode_storage_ptr(f->f_inode)) {
|
||||
fput(f);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
sdata = bpf_local_storage_update(f->f_inode,
|
||||
(struct bpf_local_storage_map *)map,
|
||||
@@ -176,14 +180,14 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
|
||||
* bpf_local_storage_update expects the owner to have a
|
||||
* valid storage pointer.
|
||||
*/
|
||||
if (!inode_storage_ptr(inode))
|
||||
if (!inode || !inode_storage_ptr(inode))
|
||||
return (unsigned long)NULL;
|
||||
|
||||
sdata = inode_storage_lookup(inode, map, true);
|
||||
if (sdata)
|
||||
return (unsigned long)sdata->data;
|
||||
|
||||
/* This helper must only called from where the inode is gurranteed
|
||||
/* This helper must only called from where the inode is guaranteed
|
||||
* to have a refcount and cannot be freed.
|
||||
*/
|
||||
if (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) {
|
||||
@@ -200,7 +204,10 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
|
||||
BPF_CALL_2(bpf_inode_storage_delete,
|
||||
struct bpf_map *, map, struct inode *, inode)
|
||||
{
|
||||
/* This helper must only called from where the inode is gurranteed
|
||||
if (!inode)
|
||||
return -EINVAL;
|
||||
|
||||
/* This helper must only called from where the inode is guaranteed
|
||||
* to have a refcount and cannot be freed.
|
||||
*/
|
||||
return inode_storage_delete(inode, map);
|
||||
|
||||
@@ -149,7 +149,11 @@ BTF_ID(func, bpf_lsm_file_ioctl)
|
||||
BTF_ID(func, bpf_lsm_file_lock)
|
||||
BTF_ID(func, bpf_lsm_file_open)
|
||||
BTF_ID(func, bpf_lsm_file_receive)
|
||||
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
BTF_ID(func, bpf_lsm_inet_conn_established)
|
||||
#endif /* CONFIG_SECURITY_NETWORK */
|
||||
|
||||
BTF_ID(func, bpf_lsm_inode_create)
|
||||
BTF_ID(func, bpf_lsm_inode_free_security)
|
||||
BTF_ID(func, bpf_lsm_inode_getattr)
|
||||
@@ -166,7 +170,11 @@ BTF_ID(func, bpf_lsm_inode_symlink)
|
||||
BTF_ID(func, bpf_lsm_inode_unlink)
|
||||
BTF_ID(func, bpf_lsm_kernel_module_request)
|
||||
BTF_ID(func, bpf_lsm_kernfs_init_security)
|
||||
|
||||
#ifdef CONFIG_KEYS
|
||||
BTF_ID(func, bpf_lsm_key_free)
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
BTF_ID(func, bpf_lsm_mmap_file)
|
||||
BTF_ID(func, bpf_lsm_netlink_send)
|
||||
BTF_ID(func, bpf_lsm_path_notify)
|
||||
@@ -181,6 +189,8 @@ BTF_ID(func, bpf_lsm_sb_show_options)
|
||||
BTF_ID(func, bpf_lsm_sb_statfs)
|
||||
BTF_ID(func, bpf_lsm_sb_umount)
|
||||
BTF_ID(func, bpf_lsm_settime)
|
||||
|
||||
#ifdef CONFIG_SECURITY_NETWORK
|
||||
BTF_ID(func, bpf_lsm_socket_accept)
|
||||
BTF_ID(func, bpf_lsm_socket_bind)
|
||||
BTF_ID(func, bpf_lsm_socket_connect)
|
||||
@@ -195,6 +205,8 @@ BTF_ID(func, bpf_lsm_socket_recvmsg)
|
||||
BTF_ID(func, bpf_lsm_socket_sendmsg)
|
||||
BTF_ID(func, bpf_lsm_socket_shutdown)
|
||||
BTF_ID(func, bpf_lsm_socket_socketpair)
|
||||
#endif /* CONFIG_SECURITY_NETWORK */
|
||||
|
||||
BTF_ID(func, bpf_lsm_syslog)
|
||||
BTF_ID(func, bpf_lsm_task_alloc)
|
||||
BTF_ID(func, bpf_lsm_task_getsecid)
|
||||
|
||||
@@ -218,7 +218,7 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
|
||||
* bpf_local_storage_update expects the owner to have a
|
||||
* valid storage pointer.
|
||||
*/
|
||||
if (!task_storage_ptr(task))
|
||||
if (!task || !task_storage_ptr(task))
|
||||
return (unsigned long)NULL;
|
||||
|
||||
sdata = task_storage_lookup(task, map, true);
|
||||
@@ -243,6 +243,9 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
|
||||
BPF_CALL_2(bpf_task_storage_delete, struct bpf_map *, map, struct task_struct *,
|
||||
task)
|
||||
{
|
||||
if (!task)
|
||||
return -EINVAL;
|
||||
|
||||
/* This helper must only be called from places where the lifetime of the task
|
||||
* is guaranteed. Either by being refcounted or by being protected
|
||||
* by an RCU read-side critical section.
|
||||
|
||||
+1
-1
@@ -4172,7 +4172,7 @@ static int btf_parse_hdr(struct btf_verifier_env *env)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (btf_data_size == hdr->hdr_len) {
|
||||
if (!btf->base_btf && btf_data_size == hdr->hdr_len) {
|
||||
btf_verifier_log(env, "No data");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+9
-3
@@ -1391,12 +1391,13 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
|
||||
if (ctx.optlen != 0) {
|
||||
*optlen = ctx.optlen;
|
||||
*kernel_optval = ctx.optval;
|
||||
/* export and don't free sockopt buf */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
sockopt_free_buf(&ctx);
|
||||
sockopt_free_buf(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1441,6 +1442,11 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx.optlen < 0) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(ctx.optval, optval,
|
||||
min(ctx.optlen, max_optlen)) != 0) {
|
||||
ret = -EFAULT;
|
||||
@@ -1458,7 +1464,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx.optlen > max_optlen) {
|
||||
if (ctx.optlen > max_optlen || ctx.optlen < 0) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ static void htab_init_buckets(struct bpf_htab *htab)
|
||||
lockdep_set_class(&htab->buckets[i].lock,
|
||||
&htab->lockdep_key);
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
|
||||
}
|
||||
|
||||
const struct bpf_func_proto bpf_map_peek_elem_proto = {
|
||||
.func = bpf_map_pop_elem,
|
||||
.func = bpf_map_peek_elem,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_CONST_MAP_PTR,
|
||||
|
||||
@@ -4,8 +4,11 @@ LIBBPF_SRCS = $(srctree)/tools/lib/bpf/
|
||||
LIBBPF_A = $(obj)/libbpf.a
|
||||
LIBBPF_OUT = $(abspath $(obj))
|
||||
|
||||
# Although not in use by libbpf's Makefile, set $(O) so that the "dummy" test
|
||||
# in tools/scripts/Makefile.include always succeeds when building the kernel
|
||||
# with $(O) pointing to a relative path, as in "make O=build bindeb-pkg".
|
||||
$(LIBBPF_A):
|
||||
$(Q)$(MAKE) -C $(LIBBPF_SRCS) OUTPUT=$(LIBBPF_OUT)/ $(LIBBPF_OUT)/libbpf.a
|
||||
$(Q)$(MAKE) -C $(LIBBPF_SRCS) O=$(LIBBPF_OUT)/ OUTPUT=$(LIBBPF_OUT)/ $(LIBBPF_OUT)/libbpf.a
|
||||
|
||||
userccflags += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi \
|
||||
-I $(srctree)/tools/lib/ -Wno-unused-result
|
||||
|
||||
@@ -115,6 +115,8 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
|
||||
|
||||
/* hash table size must be power of 2 */
|
||||
n_buckets = roundup_pow_of_two(attr->max_entries);
|
||||
if (!n_buckets)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap);
|
||||
cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/license.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/cred.h>
|
||||
@@ -2713,7 +2712,6 @@ out_unlock:
|
||||
out_put_prog:
|
||||
if (tgt_prog_fd && tgt_prog)
|
||||
bpf_prog_put(tgt_prog);
|
||||
bpf_prog_put(prog);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2826,7 +2824,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
|
||||
tp_name = prog->aux->attach_func_name;
|
||||
break;
|
||||
}
|
||||
return bpf_tracing_prog_attach(prog, 0, 0);
|
||||
err = bpf_tracing_prog_attach(prog, 0, 0);
|
||||
if (err >= 0)
|
||||
return err;
|
||||
goto out_put_prog;
|
||||
case BPF_PROG_TYPE_RAW_TRACEPOINT:
|
||||
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
|
||||
if (strncpy_from_user(buf,
|
||||
|
||||
@@ -37,7 +37,7 @@ retry:
|
||||
if (!task) {
|
||||
++*tid;
|
||||
goto retry;
|
||||
} else if (skip_if_dup_files && task->tgid != task->pid &&
|
||||
} else if (skip_if_dup_files && !thread_group_leader(task) &&
|
||||
task->files == task->group_leader->files) {
|
||||
put_task_struct(task);
|
||||
task = NULL;
|
||||
@@ -151,13 +151,14 @@ again:
|
||||
curr_task = info->task;
|
||||
curr_fd = info->fd;
|
||||
} else {
|
||||
curr_task = task_seq_get_next(ns, &curr_tid, true);
|
||||
if (!curr_task) {
|
||||
info->task = NULL;
|
||||
return NULL;
|
||||
}
|
||||
curr_task = task_seq_get_next(ns, &curr_tid, true);
|
||||
if (!curr_task) {
|
||||
info->task = NULL;
|
||||
info->tid = curr_tid;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set info->task and info->tid */
|
||||
/* set info->task and info->tid */
|
||||
info->task = curr_task;
|
||||
if (curr_tid == info->tid) {
|
||||
curr_fd = info->fd;
|
||||
|
||||
+25
-21
@@ -2217,6 +2217,8 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
|
||||
case PTR_TO_RDWR_BUF:
|
||||
case PTR_TO_RDWR_BUF_OR_NULL:
|
||||
case PTR_TO_PERCPU_BTF_ID:
|
||||
case PTR_TO_MEM:
|
||||
case PTR_TO_MEM_OR_NULL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -5311,7 +5313,7 @@ static bool signed_add_overflows(s64 a, s64 b)
|
||||
return res < a;
|
||||
}
|
||||
|
||||
static bool signed_add32_overflows(s64 a, s64 b)
|
||||
static bool signed_add32_overflows(s32 a, s32 b)
|
||||
{
|
||||
/* Do the add in u32, where overflow is well-defined */
|
||||
s32 res = (s32)((u32)a + (u32)b);
|
||||
@@ -5321,7 +5323,7 @@ static bool signed_add32_overflows(s64 a, s64 b)
|
||||
return res < a;
|
||||
}
|
||||
|
||||
static bool signed_sub_overflows(s32 a, s32 b)
|
||||
static bool signed_sub_overflows(s64 a, s64 b)
|
||||
{
|
||||
/* Do the sub in u64, where overflow is well-defined */
|
||||
s64 res = (s64)((u64)a - (u64)b);
|
||||
@@ -5333,7 +5335,7 @@ static bool signed_sub_overflows(s32 a, s32 b)
|
||||
|
||||
static bool signed_sub32_overflows(s32 a, s32 b)
|
||||
{
|
||||
/* Do the sub in u64, where overflow is well-defined */
|
||||
/* Do the sub in u32, where overflow is well-defined */
|
||||
s32 res = (s32)((u32)a - (u32)b);
|
||||
|
||||
if (b < 0)
|
||||
@@ -6875,7 +6877,7 @@ static int is_branch32_taken(struct bpf_reg_state *reg, u32 val, u8 opcode)
|
||||
case BPF_JSGT:
|
||||
if (reg->s32_min_value > sval)
|
||||
return 1;
|
||||
else if (reg->s32_max_value < sval)
|
||||
else if (reg->s32_max_value <= sval)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
@@ -6948,7 +6950,7 @@ static int is_branch64_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
|
||||
case BPF_JSGT:
|
||||
if (reg->smin_value > sval)
|
||||
return 1;
|
||||
else if (reg->smax_value < sval)
|
||||
else if (reg->smax_value <= sval)
|
||||
return 0;
|
||||
break;
|
||||
case BPF_JLT:
|
||||
@@ -8588,7 +8590,11 @@ static bool range_within(struct bpf_reg_state *old,
|
||||
return old->umin_value <= cur->umin_value &&
|
||||
old->umax_value >= cur->umax_value &&
|
||||
old->smin_value <= cur->smin_value &&
|
||||
old->smax_value >= cur->smax_value;
|
||||
old->smax_value >= cur->smax_value &&
|
||||
old->u32_min_value <= cur->u32_min_value &&
|
||||
old->u32_max_value >= cur->u32_max_value &&
|
||||
old->s32_min_value <= cur->s32_min_value &&
|
||||
old->s32_max_value >= cur->s32_max_value;
|
||||
}
|
||||
|
||||
/* Maximum number of register states that can exist at once */
|
||||
@@ -10997,30 +11003,28 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
|
||||
insn->code == (BPF_ALU | BPF_MOD | BPF_X) ||
|
||||
insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
|
||||
bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
|
||||
struct bpf_insn mask_and_div[] = {
|
||||
BPF_MOV32_REG(insn->src_reg, insn->src_reg),
|
||||
bool isdiv = BPF_OP(insn->code) == BPF_DIV;
|
||||
struct bpf_insn *patchlet;
|
||||
struct bpf_insn chk_and_div[] = {
|
||||
/* Rx div 0 -> 0 */
|
||||
BPF_JMP_IMM(BPF_JNE, insn->src_reg, 0, 2),
|
||||
BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
|
||||
BPF_JNE | BPF_K, insn->src_reg,
|
||||
0, 2, 0),
|
||||
BPF_ALU32_REG(BPF_XOR, insn->dst_reg, insn->dst_reg),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 1),
|
||||
*insn,
|
||||
};
|
||||
struct bpf_insn mask_and_mod[] = {
|
||||
BPF_MOV32_REG(insn->src_reg, insn->src_reg),
|
||||
struct bpf_insn chk_and_mod[] = {
|
||||
/* Rx mod 0 -> Rx */
|
||||
BPF_JMP_IMM(BPF_JEQ, insn->src_reg, 0, 1),
|
||||
BPF_RAW_INSN((is64 ? BPF_JMP : BPF_JMP32) |
|
||||
BPF_JEQ | BPF_K, insn->src_reg,
|
||||
0, 1, 0),
|
||||
*insn,
|
||||
};
|
||||
struct bpf_insn *patchlet;
|
||||
|
||||
if (insn->code == (BPF_ALU64 | BPF_DIV | BPF_X) ||
|
||||
insn->code == (BPF_ALU | BPF_DIV | BPF_X)) {
|
||||
patchlet = mask_and_div + (is64 ? 1 : 0);
|
||||
cnt = ARRAY_SIZE(mask_and_div) - (is64 ? 1 : 0);
|
||||
} else {
|
||||
patchlet = mask_and_mod + (is64 ? 1 : 0);
|
||||
cnt = ARRAY_SIZE(mask_and_mod) - (is64 ? 1 : 0);
|
||||
}
|
||||
patchlet = isdiv ? chk_and_div : chk_and_mod;
|
||||
cnt = isdiv ? ARRAY_SIZE(chk_and_div) :
|
||||
ARRAY_SIZE(chk_and_mod);
|
||||
|
||||
new_prog = bpf_patch_insn_data(env, i + delta, patchlet, cnt);
|
||||
if (!new_prog)
|
||||
|
||||
@@ -917,6 +917,9 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||
for_each_subsys(ss, i) {
|
||||
if (strcmp(param->key, ss->legacy_name))
|
||||
continue;
|
||||
if (!cgroup_ssid_enabled(i) || cgroup1_ssid_disabled(i))
|
||||
return invalfc(fc, "Disabled controller '%s'",
|
||||
param->key);
|
||||
ctx->subsys_mask |= (1 << i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3564,6 +3564,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
|
||||
{
|
||||
struct psi_trigger *new;
|
||||
struct cgroup *cgrp;
|
||||
struct psi_group *psi;
|
||||
|
||||
cgrp = cgroup_kn_lock_live(of->kn, false);
|
||||
if (!cgrp)
|
||||
@@ -3572,7 +3573,8 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
|
||||
cgroup_get(cgrp);
|
||||
cgroup_kn_unlock(of->kn);
|
||||
|
||||
new = psi_trigger_create(&cgrp->psi, buf, nbytes, res);
|
||||
psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;
|
||||
new = psi_trigger_create(psi, buf, nbytes, res);
|
||||
if (IS_ERR(new)) {
|
||||
cgroup_put(cgrp);
|
||||
return PTR_ERR(new);
|
||||
|
||||
@@ -81,7 +81,6 @@ CONFIG_INPUT_JOYSTICK=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_TABLET=y
|
||||
CONFIG_INPUT_UINPUT=y
|
||||
CONFIG_ION=y
|
||||
CONFIG_JOYSTICK_XPAD=y
|
||||
CONFIG_JOYSTICK_XPAD_FF=y
|
||||
CONFIG_JOYSTICK_XPAD_LEDS=y
|
||||
|
||||
@@ -36,7 +36,7 @@ struct map_benchmark {
|
||||
__s32 node; /* which numa node this benchmark will run on */
|
||||
__u32 dma_bits; /* DMA addressing capability */
|
||||
__u32 dma_dir; /* DMA data direction */
|
||||
__u64 expansion[10]; /* For future use */
|
||||
__u8 expansion[84]; /* For future use */
|
||||
};
|
||||
|
||||
struct map_benchmark_data {
|
||||
@@ -147,8 +147,10 @@ static int do_map_benchmark(struct map_benchmark_data *map)
|
||||
atomic64_set(&map->sum_sq_unmap, 0);
|
||||
atomic64_set(&map->loops, 0);
|
||||
|
||||
for (i = 0; i < threads; i++)
|
||||
for (i = 0; i < threads; i++) {
|
||||
get_task_struct(tsk[i]);
|
||||
wake_up_process(tsk[i]);
|
||||
}
|
||||
|
||||
msleep_interruptible(map->bparam.seconds * 1000);
|
||||
|
||||
@@ -183,6 +185,8 @@ static int do_map_benchmark(struct map_benchmark_data *map)
|
||||
}
|
||||
|
||||
out:
|
||||
for (i = 0; i < threads; i++)
|
||||
put_task_struct(tsk[i]);
|
||||
put_device(map->dev);
|
||||
kfree(tsk);
|
||||
return ret;
|
||||
|
||||
+3
-11
@@ -209,26 +209,18 @@ static void exit_to_user_mode_prepare(struct pt_regs *regs)
|
||||
lockdep_sys_exit();
|
||||
}
|
||||
|
||||
#ifndef _TIF_SINGLESTEP
|
||||
static inline bool report_single_step(unsigned long work)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* If SYSCALL_EMU is set, then the only reason to report is when
|
||||
* TIF_SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall
|
||||
* SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP). This syscall
|
||||
* instruction has been already reported in syscall_enter_from_user_mode().
|
||||
*/
|
||||
static inline bool report_single_step(unsigned long work)
|
||||
{
|
||||
if (!(work & SYSCALL_WORK_SYSCALL_EMU))
|
||||
if (work & SYSCALL_WORK_SYSCALL_EMU)
|
||||
return false;
|
||||
|
||||
return !!(current_thread_info()->flags & _TIF_SINGLESTEP);
|
||||
return work & SYSCALL_WORK_SYSCALL_EXIT_TRAP;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void syscall_exit_work(struct pt_regs *regs, unsigned long work)
|
||||
{
|
||||
|
||||
@@ -50,10 +50,10 @@ bool syscall_user_dispatch(struct pt_regs *regs)
|
||||
if (unlikely(__get_user(state, sd->selector)))
|
||||
do_exit(SIGSEGV);
|
||||
|
||||
if (likely(state == PR_SYS_DISPATCH_OFF))
|
||||
if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW))
|
||||
return false;
|
||||
|
||||
if (state != PR_SYS_DISPATCH_ON)
|
||||
if (state != SYSCALL_DISPATCH_FILTER_BLOCK)
|
||||
do_exit(SIGSYS);
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -819,9 +819,8 @@ void __init fork_init(void)
|
||||
init_task.signal->rlim[RLIMIT_SIGPENDING] =
|
||||
init_task.signal->rlim[RLIMIT_NPROC];
|
||||
|
||||
for (i = 0; i < UCOUNT_COUNTS; i++) {
|
||||
for (i = 0; i < UCOUNT_COUNTS; i++)
|
||||
init_user_ns.ucount_max[i] = max_threads/2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache",
|
||||
@@ -1654,9 +1653,8 @@ static inline void init_task_pid_links(struct task_struct *task)
|
||||
{
|
||||
enum pid_type type;
|
||||
|
||||
for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) {
|
||||
for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type)
|
||||
INIT_HLIST_NODE(&task->pid_links[type]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
||||
+96
-123
@@ -763,6 +763,29 @@ static struct futex_pi_state *alloc_pi_state(void)
|
||||
return pi_state;
|
||||
}
|
||||
|
||||
static void pi_state_update_owner(struct futex_pi_state *pi_state,
|
||||
struct task_struct *new_owner)
|
||||
{
|
||||
struct task_struct *old_owner = pi_state->owner;
|
||||
|
||||
lockdep_assert_held(&pi_state->pi_mutex.wait_lock);
|
||||
|
||||
if (old_owner) {
|
||||
raw_spin_lock(&old_owner->pi_lock);
|
||||
WARN_ON(list_empty(&pi_state->list));
|
||||
list_del_init(&pi_state->list);
|
||||
raw_spin_unlock(&old_owner->pi_lock);
|
||||
}
|
||||
|
||||
if (new_owner) {
|
||||
raw_spin_lock(&new_owner->pi_lock);
|
||||
WARN_ON(!list_empty(&pi_state->list));
|
||||
list_add(&pi_state->list, &new_owner->pi_state_list);
|
||||
pi_state->owner = new_owner;
|
||||
raw_spin_unlock(&new_owner->pi_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_pi_state(struct futex_pi_state *pi_state)
|
||||
{
|
||||
WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount));
|
||||
@@ -785,17 +808,11 @@ static void put_pi_state(struct futex_pi_state *pi_state)
|
||||
* and has cleaned up the pi_state already
|
||||
*/
|
||||
if (pi_state->owner) {
|
||||
struct task_struct *owner;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags);
|
||||
owner = pi_state->owner;
|
||||
if (owner) {
|
||||
raw_spin_lock(&owner->pi_lock);
|
||||
list_del_init(&pi_state->list);
|
||||
raw_spin_unlock(&owner->pi_lock);
|
||||
}
|
||||
rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner);
|
||||
pi_state_update_owner(pi_state, NULL);
|
||||
rt_mutex_proxy_unlock(&pi_state->pi_mutex);
|
||||
raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags);
|
||||
}
|
||||
|
||||
@@ -941,7 +958,8 @@ static inline void exit_pi_state_list(struct task_struct *curr) { }
|
||||
* FUTEX_OWNER_DIED bit. See [4]
|
||||
*
|
||||
* [10] There is no transient state which leaves owner and user space
|
||||
* TID out of sync.
|
||||
* TID out of sync. Except one error case where the kernel is denied
|
||||
* write access to the user address, see fixup_pi_state_owner().
|
||||
*
|
||||
*
|
||||
* Serialization and lifetime rules:
|
||||
@@ -1521,26 +1539,15 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* This is a point of no return; once we modify the uval there is no
|
||||
* going back and subsequent operations must not fail.
|
||||
*/
|
||||
|
||||
raw_spin_lock(&pi_state->owner->pi_lock);
|
||||
WARN_ON(list_empty(&pi_state->list));
|
||||
list_del_init(&pi_state->list);
|
||||
raw_spin_unlock(&pi_state->owner->pi_lock);
|
||||
|
||||
raw_spin_lock(&new_owner->pi_lock);
|
||||
WARN_ON(!list_empty(&pi_state->list));
|
||||
list_add(&pi_state->list, &new_owner->pi_state_list);
|
||||
pi_state->owner = new_owner;
|
||||
raw_spin_unlock(&new_owner->pi_lock);
|
||||
|
||||
postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
|
||||
if (!ret) {
|
||||
/*
|
||||
* This is a point of no return; once we modified the uval
|
||||
* there is no going back and subsequent operations must
|
||||
* not fail.
|
||||
*/
|
||||
pi_state_update_owner(pi_state, new_owner);
|
||||
postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
@@ -2323,18 +2330,13 @@ static void unqueue_me_pi(struct futex_q *q)
|
||||
spin_unlock(q->lock_ptr);
|
||||
}
|
||||
|
||||
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
|
||||
struct task_struct *argowner)
|
||||
static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
|
||||
struct task_struct *argowner)
|
||||
{
|
||||
struct futex_pi_state *pi_state = q->pi_state;
|
||||
u32 uval, curval, newval;
|
||||
struct task_struct *oldowner, *newowner;
|
||||
u32 newtid;
|
||||
int ret, err = 0;
|
||||
|
||||
lockdep_assert_held(q->lock_ptr);
|
||||
|
||||
raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
u32 uval, curval, newval, newtid;
|
||||
int err = 0;
|
||||
|
||||
oldowner = pi_state->owner;
|
||||
|
||||
@@ -2368,14 +2370,12 @@ retry:
|
||||
* We raced against a concurrent self; things are
|
||||
* already fixed up. Nothing to do.
|
||||
*/
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
|
||||
/* We got the lock after all, nothing to fix. */
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
/* We got the lock. pi_state is correct. Tell caller. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2402,8 +2402,7 @@ retry:
|
||||
* We raced against a concurrent self; things are
|
||||
* already fixed up. Nothing to do.
|
||||
*/
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
return 1;
|
||||
}
|
||||
newowner = argowner;
|
||||
}
|
||||
@@ -2433,22 +2432,9 @@ retry:
|
||||
* We fixed up user space. Now we need to fix the pi_state
|
||||
* itself.
|
||||
*/
|
||||
if (pi_state->owner != NULL) {
|
||||
raw_spin_lock(&pi_state->owner->pi_lock);
|
||||
WARN_ON(list_empty(&pi_state->list));
|
||||
list_del_init(&pi_state->list);
|
||||
raw_spin_unlock(&pi_state->owner->pi_lock);
|
||||
}
|
||||
pi_state_update_owner(pi_state, newowner);
|
||||
|
||||
pi_state->owner = newowner;
|
||||
|
||||
raw_spin_lock(&newowner->pi_lock);
|
||||
WARN_ON(!list_empty(&pi_state->list));
|
||||
list_add(&pi_state->list, &newowner->pi_state_list);
|
||||
raw_spin_unlock(&newowner->pi_lock);
|
||||
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
|
||||
return 0;
|
||||
return argowner == current;
|
||||
|
||||
/*
|
||||
* In order to reschedule or handle a page fault, we need to drop the
|
||||
@@ -2469,17 +2455,16 @@ handle_err:
|
||||
|
||||
switch (err) {
|
||||
case -EFAULT:
|
||||
ret = fault_in_user_writeable(uaddr);
|
||||
err = fault_in_user_writeable(uaddr);
|
||||
break;
|
||||
|
||||
case -EAGAIN:
|
||||
cond_resched();
|
||||
ret = 0;
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
ret = err;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2489,17 +2474,44 @@ handle_err:
|
||||
/*
|
||||
* Check if someone else fixed it for us:
|
||||
*/
|
||||
if (pi_state->owner != oldowner) {
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (pi_state->owner != oldowner)
|
||||
return argowner == current;
|
||||
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
/* Retry if err was -EAGAIN or the fault in succeeded */
|
||||
if (!err)
|
||||
goto retry;
|
||||
|
||||
goto retry;
|
||||
/*
|
||||
* fault_in_user_writeable() failed so user state is immutable. At
|
||||
* best we can make the kernel state consistent but user state will
|
||||
* be most likely hosed and any subsequent unlock operation will be
|
||||
* rejected due to PI futex rule [10].
|
||||
*
|
||||
* Ensure that the rtmutex owner is also the pi_state owner despite
|
||||
* the user space value claiming something different. There is no
|
||||
* point in unlocking the rtmutex if current is the owner as it
|
||||
* would need to wait until the next waiter has taken the rtmutex
|
||||
* to guarantee consistent state. Keep it simple. Userspace asked
|
||||
* for this wreckaged state.
|
||||
*
|
||||
* The rtmutex has an owner - either current or some other
|
||||
* task. See the EAGAIN loop above.
|
||||
*/
|
||||
pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex));
|
||||
|
||||
out_unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
|
||||
struct task_struct *argowner)
|
||||
{
|
||||
struct futex_pi_state *pi_state = q->pi_state;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(q->lock_ptr);
|
||||
|
||||
raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
ret = __fixup_pi_state_owner(uaddr, q, argowner);
|
||||
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -2523,8 +2535,6 @@ static long futex_wait_restart(struct restart_block *restart);
|
||||
*/
|
||||
static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (locked) {
|
||||
/*
|
||||
* Got the lock. We might not be the anticipated owner if we
|
||||
@@ -2535,8 +2545,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
|
||||
* stable state, anything else needs more attention.
|
||||
*/
|
||||
if (q->pi_state->owner != current)
|
||||
ret = fixup_pi_state_owner(uaddr, q, current);
|
||||
return ret ? ret : locked;
|
||||
return fixup_pi_state_owner(uaddr, q, current);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2547,23 +2557,17 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
|
||||
* Another speculative read; pi_state->owner == current is unstable
|
||||
* but needs our attention.
|
||||
*/
|
||||
if (q->pi_state->owner == current) {
|
||||
ret = fixup_pi_state_owner(uaddr, q, NULL);
|
||||
return ret;
|
||||
}
|
||||
if (q->pi_state->owner == current)
|
||||
return fixup_pi_state_owner(uaddr, q, NULL);
|
||||
|
||||
/*
|
||||
* Paranoia check. If we did not take the lock, then we should not be
|
||||
* the owner of the rt_mutex.
|
||||
* the owner of the rt_mutex. Warn and establish consistent state.
|
||||
*/
|
||||
if (rt_mutex_owner(&q->pi_state->pi_mutex) == current) {
|
||||
printk(KERN_ERR "fixup_owner: ret = %d pi-mutex: %p "
|
||||
"pi-state %p\n", ret,
|
||||
q->pi_state->pi_mutex.owner,
|
||||
q->pi_state->owner);
|
||||
}
|
||||
if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current))
|
||||
return fixup_pi_state_owner(uaddr, q, current);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2771,7 +2775,6 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
|
||||
ktime_t *time, int trylock)
|
||||
{
|
||||
struct hrtimer_sleeper timeout, *to;
|
||||
struct futex_pi_state *pi_state = NULL;
|
||||
struct task_struct *exiting = NULL;
|
||||
struct rt_mutex_waiter rt_waiter;
|
||||
struct futex_hash_bucket *hb;
|
||||
@@ -2907,23 +2910,8 @@ no_block:
|
||||
if (res)
|
||||
ret = (res < 0) ? res : 0;
|
||||
|
||||
/*
|
||||
* If fixup_owner() faulted and was unable to handle the fault, unlock
|
||||
* it and return the fault to userspace.
|
||||
*/
|
||||
if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current)) {
|
||||
pi_state = q.pi_state;
|
||||
get_pi_state(pi_state);
|
||||
}
|
||||
|
||||
/* Unqueue and drop the lock */
|
||||
unqueue_me_pi(&q);
|
||||
|
||||
if (pi_state) {
|
||||
rt_mutex_futex_unlock(&pi_state->pi_mutex);
|
||||
put_pi_state(pi_state);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
out_unlock_put_key:
|
||||
@@ -3183,7 +3171,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
||||
u32 __user *uaddr2)
|
||||
{
|
||||
struct hrtimer_sleeper timeout, *to;
|
||||
struct futex_pi_state *pi_state = NULL;
|
||||
struct rt_mutex_waiter rt_waiter;
|
||||
struct futex_hash_bucket *hb;
|
||||
union futex_key key2 = FUTEX_KEY_INIT;
|
||||
@@ -3261,16 +3248,17 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
||||
if (q.pi_state && (q.pi_state->owner != current)) {
|
||||
spin_lock(q.lock_ptr);
|
||||
ret = fixup_pi_state_owner(uaddr2, &q, current);
|
||||
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
|
||||
pi_state = q.pi_state;
|
||||
get_pi_state(pi_state);
|
||||
}
|
||||
/*
|
||||
* Drop the reference to the pi state which
|
||||
* the requeue_pi() code acquired for us.
|
||||
*/
|
||||
put_pi_state(q.pi_state);
|
||||
spin_unlock(q.lock_ptr);
|
||||
/*
|
||||
* Adjust the return value. It's either -EFAULT or
|
||||
* success (1) but the caller expects 0 for success.
|
||||
*/
|
||||
ret = ret < 0 ? ret : 0;
|
||||
}
|
||||
} else {
|
||||
struct rt_mutex *pi_mutex;
|
||||
@@ -3301,25 +3289,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
||||
if (res)
|
||||
ret = (res < 0) ? res : 0;
|
||||
|
||||
/*
|
||||
* If fixup_pi_state_owner() faulted and was unable to handle
|
||||
* the fault, unlock the rt_mutex and return the fault to
|
||||
* userspace.
|
||||
*/
|
||||
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
|
||||
pi_state = q.pi_state;
|
||||
get_pi_state(pi_state);
|
||||
}
|
||||
|
||||
/* Unqueue and drop the lock. */
|
||||
unqueue_me_pi(&q);
|
||||
}
|
||||
|
||||
if (pi_state) {
|
||||
rt_mutex_futex_unlock(&pi_state->pi_mutex);
|
||||
put_pi_state(pi_state);
|
||||
}
|
||||
|
||||
if (ret == -EINTR) {
|
||||
/*
|
||||
* We've already been requeued, but cannot restart by calling
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ menu "GCOV-based kernel profiling"
|
||||
config GCOV_KERNEL
|
||||
bool "Enable gcov-based kernel profiling"
|
||||
depends on DEBUG_FS
|
||||
select CONSTRUCTORS if !UML
|
||||
select CONSTRUCTORS
|
||||
default n
|
||||
help
|
||||
This option enables gcov-based code profiling (e.g. for code coverage
|
||||
|
||||
@@ -2859,3 +2859,4 @@ bool irq_check_status_bit(unsigned int irq, unsigned int bitmask)
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_check_status_bit);
|
||||
|
||||
+21
-25
@@ -402,7 +402,7 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
|
||||
struct msi_domain_ops *ops = info->ops;
|
||||
struct irq_data *irq_data;
|
||||
struct msi_desc *desc;
|
||||
msi_alloc_info_t arg;
|
||||
msi_alloc_info_t arg = { };
|
||||
int i, ret, virq;
|
||||
bool can_reserve;
|
||||
|
||||
@@ -436,22 +436,22 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
|
||||
|
||||
can_reserve = msi_check_reservation_mode(domain, info, dev);
|
||||
|
||||
for_each_msi_entry(desc, dev) {
|
||||
virq = desc->irq;
|
||||
if (desc->nvec_used == 1)
|
||||
dev_dbg(dev, "irq %d for MSI\n", virq);
|
||||
else
|
||||
/*
|
||||
* This flag is set by the PCI layer as we need to activate
|
||||
* the MSI entries before the PCI layer enables MSI in the
|
||||
* card. Otherwise the card latches a random msi message.
|
||||
*/
|
||||
if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
|
||||
goto skip_activate;
|
||||
|
||||
for_each_msi_vector(desc, i, dev) {
|
||||
if (desc->irq == i) {
|
||||
virq = desc->irq;
|
||||
dev_dbg(dev, "irq [%d-%d] for MSI\n",
|
||||
virq, virq + desc->nvec_used - 1);
|
||||
/*
|
||||
* This flag is set by the PCI layer as we need to activate
|
||||
* the MSI entries before the PCI layer enables MSI in the
|
||||
* card. Otherwise the card latches a random msi message.
|
||||
*/
|
||||
if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
|
||||
continue;
|
||||
}
|
||||
|
||||
irq_data = irq_domain_get_irq_data(domain, desc->irq);
|
||||
irq_data = irq_domain_get_irq_data(domain, i);
|
||||
if (!can_reserve) {
|
||||
irqd_clr_can_reserve(irq_data);
|
||||
if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
|
||||
@@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
skip_activate:
|
||||
/*
|
||||
* If these interrupts use reservation mode, clear the activated bit
|
||||
* so request_irq() will assign the final vector.
|
||||
*/
|
||||
if (can_reserve) {
|
||||
for_each_msi_entry(desc, dev) {
|
||||
irq_data = irq_domain_get_irq_data(domain, desc->irq);
|
||||
for_each_msi_vector(desc, i, dev) {
|
||||
irq_data = irq_domain_get_irq_data(domain, i);
|
||||
irqd_clr_activated(irq_data);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
for_each_msi_entry(desc, dev) {
|
||||
struct irq_data *irqd;
|
||||
|
||||
if (desc->irq == virq)
|
||||
break;
|
||||
|
||||
irqd = irq_domain_get_irq_data(domain, desc->irq);
|
||||
if (irqd_is_activated(irqd))
|
||||
irq_domain_deactivate_irq(irqd);
|
||||
for_each_msi_vector(desc, i, dev) {
|
||||
irq_data = irq_domain_get_irq_data(domain, i);
|
||||
if (irqd_is_activated(irq_data))
|
||||
irq_domain_deactivate_irq(irq_data);
|
||||
}
|
||||
msi_domain_free_irqs(domain, dev);
|
||||
return ret;
|
||||
|
||||
@@ -1134,7 +1134,6 @@ int kernel_kexec(void)
|
||||
|
||||
#ifdef CONFIG_KEXEC_JUMP
|
||||
if (kexec_image->preserve_context) {
|
||||
lock_system_sleep();
|
||||
pm_prepare_console();
|
||||
error = freeze_processes();
|
||||
if (error) {
|
||||
@@ -1197,7 +1196,6 @@ int kernel_kexec(void)
|
||||
thaw_processes();
|
||||
Restore_console:
|
||||
pm_restore_console();
|
||||
unlock_system_sleep();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+28
-8
@@ -1954,28 +1954,48 @@ bool __weak arch_kprobe_on_func_entry(unsigned long offset)
|
||||
return !offset;
|
||||
}
|
||||
|
||||
bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset)
|
||||
/**
|
||||
* kprobe_on_func_entry() -- check whether given address is function entry
|
||||
* @addr: Target address
|
||||
* @sym: Target symbol name
|
||||
* @offset: The offset from the symbol or the address
|
||||
*
|
||||
* This checks whether the given @addr+@offset or @sym+@offset is on the
|
||||
* function entry address or not.
|
||||
* This returns 0 if it is the function entry, or -EINVAL if it is not.
|
||||
* And also it returns -ENOENT if it fails the symbol or address lookup.
|
||||
* Caller must pass @addr or @sym (either one must be NULL), or this
|
||||
* returns -EINVAL.
|
||||
*/
|
||||
int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset)
|
||||
{
|
||||
kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset);
|
||||
|
||||
if (IS_ERR(kp_addr))
|
||||
return false;
|
||||
return PTR_ERR(kp_addr);
|
||||
|
||||
if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) ||
|
||||
!arch_kprobe_on_func_entry(offset))
|
||||
return false;
|
||||
if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset))
|
||||
return -ENOENT;
|
||||
|
||||
return true;
|
||||
if (!arch_kprobe_on_func_entry(offset))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_kretprobe(struct kretprobe *rp)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct kretprobe_instance *inst;
|
||||
int i;
|
||||
void *addr;
|
||||
|
||||
if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
|
||||
ret = kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If only rp->kp.addr is specified, check reregistering kprobes */
|
||||
if (rp->kp.addr && check_kprobe_rereg(&rp->kp))
|
||||
return -EINVAL;
|
||||
|
||||
if (kretprobe_blacklist_size) {
|
||||
|
||||
+27
-2
@@ -294,7 +294,7 @@ static int kthread(void *_create)
|
||||
do_exit(ret);
|
||||
}
|
||||
|
||||
/* called from do_fork() to get node information for about to be created task */
|
||||
/* called from kernel_clone() to get node information for about to be created task */
|
||||
int tsk_fork_get_node(struct task_struct *tsk)
|
||||
{
|
||||
#ifdef CONFIG_NUMA
|
||||
@@ -493,11 +493,36 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
|
||||
return p;
|
||||
kthread_bind(p, cpu);
|
||||
/* CPU hotplug need to bind once again when unparking the thread. */
|
||||
set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags);
|
||||
to_kthread(p)->cpu = cpu;
|
||||
return p;
|
||||
}
|
||||
|
||||
void kthread_set_per_cpu(struct task_struct *k, int cpu)
|
||||
{
|
||||
struct kthread *kthread = to_kthread(k);
|
||||
if (!kthread)
|
||||
return;
|
||||
|
||||
WARN_ON_ONCE(!(k->flags & PF_NO_SETAFFINITY));
|
||||
|
||||
if (cpu < 0) {
|
||||
clear_bit(KTHREAD_IS_PER_CPU, &kthread->flags);
|
||||
return;
|
||||
}
|
||||
|
||||
kthread->cpu = cpu;
|
||||
set_bit(KTHREAD_IS_PER_CPU, &kthread->flags);
|
||||
}
|
||||
|
||||
bool kthread_is_per_cpu(struct task_struct *k)
|
||||
{
|
||||
struct kthread *kthread = to_kthread(k);
|
||||
if (!kthread)
|
||||
return false;
|
||||
|
||||
return test_bit(KTHREAD_IS_PER_CPU, &kthread->flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* kthread_unpark - unpark a thread created by kthread_create().
|
||||
* @k: thread created by kthread_create().
|
||||
|
||||
@@ -79,7 +79,7 @@ module_param(lock_stat, int, 0644);
|
||||
DEFINE_PER_CPU(unsigned int, lockdep_recursion);
|
||||
EXPORT_PER_CPU_SYMBOL_GPL(lockdep_recursion);
|
||||
|
||||
static inline bool lockdep_enabled(void)
|
||||
static __always_inline bool lockdep_enabled(void)
|
||||
{
|
||||
if (!debug_locks)
|
||||
return false;
|
||||
@@ -5271,12 +5271,15 @@ static void __lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie cookie
|
||||
/*
|
||||
* Check whether we follow the irq-flags state precisely:
|
||||
*/
|
||||
static void check_flags(unsigned long flags)
|
||||
static noinstr void check_flags(unsigned long flags)
|
||||
{
|
||||
#if defined(CONFIG_PROVE_LOCKING) && defined(CONFIG_DEBUG_LOCKDEP)
|
||||
if (!debug_locks)
|
||||
return;
|
||||
|
||||
/* Get the warning out.. */
|
||||
instrumentation_begin();
|
||||
|
||||
if (irqs_disabled_flags(flags)) {
|
||||
if (DEBUG_LOCKS_WARN_ON(lockdep_hardirqs_enabled())) {
|
||||
printk("possible reason: unannotated irqs-off.\n");
|
||||
@@ -5304,6 +5307,8 @@ static void check_flags(unsigned long flags)
|
||||
|
||||
if (!debug_locks)
|
||||
print_irqtrace_events(current);
|
||||
|
||||
instrumentation_end();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1716,8 +1716,7 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
|
||||
* possible because it belongs to the pi_state which is about to be freed
|
||||
* and it is not longer visible to other tasks.
|
||||
*/
|
||||
void rt_mutex_proxy_unlock(struct rt_mutex *lock,
|
||||
struct task_struct *proxy_owner)
|
||||
void rt_mutex_proxy_unlock(struct rt_mutex *lock)
|
||||
{
|
||||
debug_rt_mutex_proxy_unlock(lock);
|
||||
rt_mutex_set_owner(lock, NULL);
|
||||
|
||||
@@ -133,8 +133,7 @@ enum rtmutex_chainwalk {
|
||||
extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
|
||||
extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
|
||||
struct task_struct *proxy_owner);
|
||||
extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
|
||||
struct task_struct *proxy_owner);
|
||||
extern void rt_mutex_proxy_unlock(struct rt_mutex *lock);
|
||||
extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter);
|
||||
extern int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
|
||||
struct rt_mutex_waiter *waiter,
|
||||
|
||||
+1
-1
@@ -497,10 +497,10 @@ static int swap_writer_finish(struct swap_map_handle *handle,
|
||||
unsigned int flags, int error)
|
||||
{
|
||||
if (!error) {
|
||||
flush_swap_writer(handle);
|
||||
pr_info("S");
|
||||
error = mark_swapfiles(handle, flags);
|
||||
pr_cont("|\n");
|
||||
flush_swap_writer(handle);
|
||||
}
|
||||
|
||||
if (error)
|
||||
|
||||
+29
-11
@@ -1291,11 +1291,16 @@ static size_t info_print_prefix(const struct printk_info *info, bool syslog,
|
||||
* done:
|
||||
*
|
||||
* - Add prefix for each line.
|
||||
* - Drop truncated lines that no longer fit into the buffer.
|
||||
* - Add the trailing newline that has been removed in vprintk_store().
|
||||
* - Drop truncated lines that do not longer fit into the buffer.
|
||||
* - Add a string terminator.
|
||||
*
|
||||
* Since the produced string is always terminated, the maximum possible
|
||||
* return value is @r->text_buf_size - 1;
|
||||
*
|
||||
* Return: The length of the updated/prepared text, including the added
|
||||
* prefixes and the newline. The dropped line(s) are not counted.
|
||||
* prefixes and the newline. The terminator is not counted. The dropped
|
||||
* line(s) are not counted.
|
||||
*/
|
||||
static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
bool time)
|
||||
@@ -1338,26 +1343,31 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
|
||||
/*
|
||||
* Truncate the text if there is not enough space to add the
|
||||
* prefix and a trailing newline.
|
||||
* prefix and a trailing newline and a terminator.
|
||||
*/
|
||||
if (len + prefix_len + text_len + 1 > buf_size) {
|
||||
if (len + prefix_len + text_len + 1 + 1 > buf_size) {
|
||||
/* Drop even the current line if no space. */
|
||||
if (len + prefix_len + line_len + 1 > buf_size)
|
||||
if (len + prefix_len + line_len + 1 + 1 > buf_size)
|
||||
break;
|
||||
|
||||
text_len = buf_size - len - prefix_len - 1;
|
||||
text_len = buf_size - len - prefix_len - 1 - 1;
|
||||
truncated = true;
|
||||
}
|
||||
|
||||
memmove(text + prefix_len, text, text_len);
|
||||
memcpy(text, prefix, prefix_len);
|
||||
|
||||
/*
|
||||
* Increment the prepared length to include the text and
|
||||
* prefix that were just moved+copied. Also increment for the
|
||||
* newline at the end of this line. If this is the last line,
|
||||
* there is no newline, but it will be added immediately below.
|
||||
*/
|
||||
len += prefix_len + line_len + 1;
|
||||
|
||||
if (text_len == line_len) {
|
||||
/*
|
||||
* Add the trailing newline removed in
|
||||
* vprintk_store().
|
||||
* This is the last line. Add the trailing newline
|
||||
* removed in vprintk_store().
|
||||
*/
|
||||
text[prefix_len + line_len] = '\n';
|
||||
break;
|
||||
@@ -1382,6 +1392,14 @@ static size_t record_print_text(struct printk_record *r, bool syslog,
|
||||
text_len -= line_len + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a buffer was provided, it will be terminated. Space for the
|
||||
* string terminator is guaranteed to be available. The terminator is
|
||||
* not counted in the return value.
|
||||
*/
|
||||
if (buf_size > 0)
|
||||
r->text_buf[len] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -3427,7 +3445,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
||||
while (prb_read_valid_info(prb, seq, &info, &line_count)) {
|
||||
if (r.info->seq >= dumper->next_seq)
|
||||
break;
|
||||
l += get_record_print_text_size(&info, line_count, true, time);
|
||||
l += get_record_print_text_size(&info, line_count, syslog, time);
|
||||
seq = r.info->seq + 1;
|
||||
}
|
||||
|
||||
@@ -3437,7 +3455,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
||||
&info, &line_count)) {
|
||||
if (r.info->seq >= dumper->next_seq)
|
||||
break;
|
||||
l -= get_record_print_text_size(&info, line_count, true, time);
|
||||
l -= get_record_print_text_size(&info, line_count, syslog, time);
|
||||
seq = r.info->seq + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1718,7 +1718,7 @@ static bool copy_data(struct prb_data_ring *data_ring,
|
||||
|
||||
/* Caller interested in the line count? */
|
||||
if (line_count)
|
||||
*line_count = count_lines(data, data_size);
|
||||
*line_count = count_lines(data, len);
|
||||
|
||||
/* Caller interested in the data content? */
|
||||
if (!buf || !buf_size)
|
||||
|
||||
+21
-4
@@ -241,7 +241,7 @@ static int __noreturn rcu_tasks_kthread(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Spawn RCU-tasks grace-period kthread, e.g., at core_initcall() time. */
|
||||
/* Spawn RCU-tasks grace-period kthread. */
|
||||
static void __init rcu_spawn_tasks_kthread_generic(struct rcu_tasks *rtp)
|
||||
{
|
||||
struct task_struct *t;
|
||||
@@ -564,7 +564,6 @@ static int __init rcu_spawn_tasks_kthread(void)
|
||||
rcu_spawn_tasks_kthread_generic(&rcu_tasks);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(rcu_spawn_tasks_kthread);
|
||||
|
||||
#if !defined(CONFIG_TINY_RCU)
|
||||
void show_rcu_tasks_classic_gp_kthread(void)
|
||||
@@ -692,7 +691,6 @@ static int __init rcu_spawn_tasks_rude_kthread(void)
|
||||
rcu_spawn_tasks_kthread_generic(&rcu_tasks_rude);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(rcu_spawn_tasks_rude_kthread);
|
||||
|
||||
#if !defined(CONFIG_TINY_RCU)
|
||||
void show_rcu_tasks_rude_gp_kthread(void)
|
||||
@@ -968,6 +966,11 @@ static void rcu_tasks_trace_pregp_step(void)
|
||||
static void rcu_tasks_trace_pertask(struct task_struct *t,
|
||||
struct list_head *hop)
|
||||
{
|
||||
// During early boot when there is only the one boot CPU, there
|
||||
// is no idle task for the other CPUs. Just return.
|
||||
if (unlikely(t == NULL))
|
||||
return;
|
||||
|
||||
WRITE_ONCE(t->trc_reader_special.b.need_qs, false);
|
||||
WRITE_ONCE(t->trc_reader_checked, false);
|
||||
t->trc_ipi_to_cpu = -1;
|
||||
@@ -1193,7 +1196,6 @@ static int __init rcu_spawn_tasks_trace_kthread(void)
|
||||
rcu_spawn_tasks_kthread_generic(&rcu_tasks_trace);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(rcu_spawn_tasks_trace_kthread);
|
||||
|
||||
#if !defined(CONFIG_TINY_RCU)
|
||||
void show_rcu_tasks_trace_gp_kthread(void)
|
||||
@@ -1222,6 +1224,21 @@ void show_rcu_tasks_gp_kthreads(void)
|
||||
}
|
||||
#endif /* #ifndef CONFIG_TINY_RCU */
|
||||
|
||||
void __init rcu_init_tasks_generic(void)
|
||||
{
|
||||
#ifdef CONFIG_TASKS_RCU
|
||||
rcu_spawn_tasks_kthread();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TASKS_RUDE_RCU
|
||||
rcu_spawn_tasks_rude_kthread();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TASKS_TRACE_RCU
|
||||
rcu_spawn_tasks_trace_kthread();
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* #ifdef CONFIG_TASKS_RCU_GENERIC */
|
||||
static inline void rcu_tasks_bootup_oddness(void) {}
|
||||
void show_rcu_tasks_gp_kthreads(void) {}
|
||||
|
||||
+88
-23
@@ -1796,13 +1796,28 @@ static inline bool rq_has_pinned_tasks(struct rq *rq)
|
||||
*/
|
||||
static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
|
||||
{
|
||||
/* When not in the task's cpumask, no point in looking further. */
|
||||
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
|
||||
return false;
|
||||
|
||||
if (is_per_cpu_kthread(p) || is_migration_disabled(p))
|
||||
/* migrate_disabled() must be allowed to finish. */
|
||||
if (is_migration_disabled(p))
|
||||
return cpu_online(cpu);
|
||||
|
||||
return cpu_active(cpu);
|
||||
/* Non kernel threads are not allowed during either online or offline. */
|
||||
if (!(p->flags & PF_KTHREAD))
|
||||
return cpu_active(cpu);
|
||||
|
||||
/* KTHREAD_IS_PER_CPU is always allowed. */
|
||||
if (kthread_is_per_cpu(p))
|
||||
return cpu_online(cpu);
|
||||
|
||||
/* Regular kernel threads don't get to stay during offline. */
|
||||
if (cpu_rq(cpu)->balance_push)
|
||||
return false;
|
||||
|
||||
/* But are allowed during online. */
|
||||
return cpu_online(cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2327,7 +2342,9 @@ static int __set_cpus_allowed_ptr(struct task_struct *p,
|
||||
|
||||
if (p->flags & PF_KTHREAD || is_migration_disabled(p)) {
|
||||
/*
|
||||
* Kernel threads are allowed on online && !active CPUs.
|
||||
* Kernel threads are allowed on online && !active CPUs,
|
||||
* however, during cpu-hot-unplug, even these might get pushed
|
||||
* away if not KTHREAD_IS_PER_CPU.
|
||||
*
|
||||
* Specifically, migration_disabled() tasks must not fail the
|
||||
* cpumask_any_and_distribute() pick below, esp. so on
|
||||
@@ -2371,16 +2388,6 @@ static int __set_cpus_allowed_ptr(struct task_struct *p,
|
||||
|
||||
__do_set_cpus_allowed(p, new_mask, flags);
|
||||
|
||||
if (p->flags & PF_KTHREAD) {
|
||||
/*
|
||||
* For kernel threads that do indeed end up on online &&
|
||||
* !active we want to ensure they are strict per-CPU threads.
|
||||
*/
|
||||
WARN_ON(cpumask_intersects(new_mask, cpu_online_mask) &&
|
||||
!cpumask_intersects(new_mask, cpu_active_mask) &&
|
||||
p->nr_cpus_allowed != 1);
|
||||
}
|
||||
|
||||
return affine_move_task(rq, p, &rf, dest_cpu, flags);
|
||||
|
||||
out:
|
||||
@@ -3121,6 +3128,13 @@ bool cpus_share_cache(int this_cpu, int that_cpu)
|
||||
|
||||
static inline bool ttwu_queue_cond(int cpu, int wake_flags)
|
||||
{
|
||||
/*
|
||||
* Do not complicate things with the async wake_list while the CPU is
|
||||
* in hotplug state.
|
||||
*/
|
||||
if (!cpu_active(cpu))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the CPU does not share cache, then queue the task on the
|
||||
* remote rqs wakelist to avoid accessing remote data.
|
||||
@@ -7390,8 +7404,14 @@ static void balance_push(struct rq *rq)
|
||||
/*
|
||||
* Both the cpu-hotplug and stop task are in this case and are
|
||||
* required to complete the hotplug process.
|
||||
*
|
||||
* XXX: the idle task does not match kthread_is_per_cpu() due to
|
||||
* histerical raisins.
|
||||
*/
|
||||
if (is_per_cpu_kthread(push_task) || is_migration_disabled(push_task)) {
|
||||
if (rq->idle == push_task ||
|
||||
((push_task->flags & PF_KTHREAD) && kthread_is_per_cpu(push_task)) ||
|
||||
is_migration_disabled(push_task)) {
|
||||
|
||||
/*
|
||||
* If this is the idle task on the outgoing CPU try to wake
|
||||
* up the hotplug control thread which might wait for the
|
||||
@@ -7423,7 +7443,7 @@ static void balance_push(struct rq *rq)
|
||||
/*
|
||||
* At this point need_resched() is true and we'll take the loop in
|
||||
* schedule(). The next pick is obviously going to be the stop task
|
||||
* which is_per_cpu_kthread() and will push this task away.
|
||||
* which kthread_is_per_cpu() and will push this task away.
|
||||
*/
|
||||
raw_spin_lock(&rq->lock);
|
||||
}
|
||||
@@ -7434,10 +7454,13 @@ static void balance_push_set(int cpu, bool on)
|
||||
struct rq_flags rf;
|
||||
|
||||
rq_lock_irqsave(rq, &rf);
|
||||
if (on)
|
||||
rq->balance_push = on;
|
||||
if (on) {
|
||||
WARN_ON_ONCE(rq->balance_callback);
|
||||
rq->balance_callback = &balance_push_callback;
|
||||
else
|
||||
} else if (rq->balance_callback == &balance_push_callback) {
|
||||
rq->balance_callback = NULL;
|
||||
}
|
||||
rq_unlock_irqrestore(rq, &rf);
|
||||
}
|
||||
|
||||
@@ -7555,6 +7578,10 @@ int sched_cpu_activate(unsigned int cpu)
|
||||
struct rq *rq = cpu_rq(cpu);
|
||||
struct rq_flags rf;
|
||||
|
||||
/*
|
||||
* Make sure that when the hotplug state machine does a roll-back
|
||||
* we clear balance_push. Ideally that would happen earlier...
|
||||
*/
|
||||
balance_push_set(cpu, false);
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
@@ -7603,17 +7630,27 @@ int sched_cpu_deactivate(unsigned int cpu)
|
||||
nohz_balance_exit_idle(rq);
|
||||
|
||||
set_cpu_active(cpu, false);
|
||||
|
||||
/*
|
||||
* We've cleared cpu_active_mask, wait for all preempt-disabled and RCU
|
||||
* users of this state to go away such that all new such users will
|
||||
* observe it.
|
||||
* From this point forward, this CPU will refuse to run any task that
|
||||
* is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
|
||||
* push those tasks away until this gets cleared, see
|
||||
* sched_cpu_dying().
|
||||
*/
|
||||
balance_push_set(cpu, true);
|
||||
|
||||
/*
|
||||
* We've cleared cpu_active_mask / set balance_push, wait for all
|
||||
* preempt-disabled and RCU users of this state to go away such that
|
||||
* all new such users will observe it.
|
||||
*
|
||||
* Specifically, we rely on ttwu to no longer target this CPU, see
|
||||
* ttwu_queue_cond() and is_cpu_allowed().
|
||||
*
|
||||
* Do sync before park smpboot threads to take care the rcu boost case.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
|
||||
balance_push_set(cpu, true);
|
||||
|
||||
rq_lock_irqsave(rq, &rf);
|
||||
if (rq->rd) {
|
||||
update_rq_clock(rq);
|
||||
@@ -7694,6 +7731,25 @@ static void calc_load_migrate(struct rq *rq)
|
||||
atomic_long_add(delta, &calc_load_tasks);
|
||||
}
|
||||
|
||||
static void dump_rq_tasks(struct rq *rq, const char *loglvl)
|
||||
{
|
||||
struct task_struct *g, *p;
|
||||
int cpu = cpu_of(rq);
|
||||
|
||||
lockdep_assert_held(&rq->lock);
|
||||
|
||||
printk("%sCPU%d enqueued tasks (%u total):\n", loglvl, cpu, rq->nr_running);
|
||||
for_each_process_thread(g, p) {
|
||||
if (task_cpu(p) != cpu)
|
||||
continue;
|
||||
|
||||
if (!task_on_rq_queued(p))
|
||||
continue;
|
||||
|
||||
printk("%s\tpid: %d, name: %s\n", loglvl, p->pid, p->comm);
|
||||
}
|
||||
}
|
||||
|
||||
int sched_cpu_dying(unsigned int cpu)
|
||||
{
|
||||
struct rq *rq = cpu_rq(cpu);
|
||||
@@ -7703,9 +7759,18 @@ int sched_cpu_dying(unsigned int cpu)
|
||||
sched_tick_stop(cpu);
|
||||
|
||||
rq_lock_irqsave(rq, &rf);
|
||||
BUG_ON(rq->nr_running != 1 || rq_has_pinned_tasks(rq));
|
||||
if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) {
|
||||
WARN(true, "Dying CPU not properly vacated!");
|
||||
dump_rq_tasks(rq, KERN_WARNING);
|
||||
}
|
||||
rq_unlock_irqrestore(rq, &rf);
|
||||
|
||||
/*
|
||||
* Now that the CPU is offline, make sure we're welcome
|
||||
* to new tasks once we come back up.
|
||||
*/
|
||||
balance_push_set(cpu, false);
|
||||
|
||||
calc_load_migrate(rq);
|
||||
update_max_interval();
|
||||
hrtick_clear(rq);
|
||||
|
||||
@@ -975,6 +975,7 @@ struct rq {
|
||||
unsigned long cpu_capacity_orig;
|
||||
|
||||
struct callback_head *balance_callback;
|
||||
unsigned char balance_push;
|
||||
|
||||
unsigned char nohz_idle_balance;
|
||||
unsigned char idle_balance;
|
||||
|
||||
+5
-1
@@ -2550,6 +2550,9 @@ bool get_signal(struct ksignal *ksig)
|
||||
struct signal_struct *signal = current->signal;
|
||||
int signr;
|
||||
|
||||
if (unlikely(current->task_works))
|
||||
task_work_run();
|
||||
|
||||
/*
|
||||
* For non-generic architectures, check for TIF_NOTIFY_SIGNAL so
|
||||
* that the arch handlers don't all have to do it. If we get here
|
||||
@@ -3701,7 +3704,8 @@ static bool access_pidfd_pidns(struct pid *pid)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo, siginfo_t *info)
|
||||
static int copy_siginfo_from_user_any(kernel_siginfo_t *kinfo,
|
||||
siginfo_t __user *info)
|
||||
{
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
|
||||
@@ -188,6 +188,7 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
|
||||
kfree(td);
|
||||
return PTR_ERR(tsk);
|
||||
}
|
||||
kthread_set_per_cpu(tsk, cpu);
|
||||
/*
|
||||
* Park the thread so that it could start right on the CPU
|
||||
* when it is available.
|
||||
|
||||
+4
-4
@@ -498,11 +498,11 @@ out:
|
||||
static void sync_hw_clock(struct work_struct *work);
|
||||
static DECLARE_WORK(sync_work, sync_hw_clock);
|
||||
static struct hrtimer sync_hrtimer;
|
||||
#define SYNC_PERIOD_NS (11UL * 60 * NSEC_PER_SEC)
|
||||
#define SYNC_PERIOD_NS (11ULL * 60 * NSEC_PER_SEC)
|
||||
|
||||
static enum hrtimer_restart sync_timer_callback(struct hrtimer *timer)
|
||||
{
|
||||
queue_work(system_power_efficient_wq, &sync_work);
|
||||
queue_work(system_freezable_power_efficient_wq, &sync_work);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
@@ -512,7 +512,7 @@ static void sched_sync_hw_clock(unsigned long offset_nsec, bool retry)
|
||||
ktime_t exp = ktime_set(ktime_get_real_seconds(), 0);
|
||||
|
||||
if (retry)
|
||||
exp = ktime_add_ns(exp, 2 * NSEC_PER_SEC - offset_nsec);
|
||||
exp = ktime_add_ns(exp, 2ULL * NSEC_PER_SEC - offset_nsec);
|
||||
else
|
||||
exp = ktime_add_ns(exp, SYNC_PERIOD_NS - offset_nsec);
|
||||
|
||||
@@ -668,7 +668,7 @@ void ntp_notify_cmos_timer(void)
|
||||
* just a pointless work scheduled.
|
||||
*/
|
||||
if (ntp_synced() && !hrtimer_is_queued(&sync_hrtimer))
|
||||
queue_work(system_power_efficient_wq, &sync_work);
|
||||
queue_work(system_freezable_power_efficient_wq, &sync_work);
|
||||
}
|
||||
|
||||
static void __init ntp_init_cmos_sync(void)
|
||||
|
||||
@@ -991,8 +991,7 @@ EXPORT_SYMBOL_GPL(ktime_get_seconds);
|
||||
/**
|
||||
* ktime_get_real_seconds - Get the seconds portion of CLOCK_REALTIME
|
||||
*
|
||||
* Returns the wall clock seconds since 1970. This replaces the
|
||||
* get_seconds() interface which is not y2038 safe on 32bit systems.
|
||||
* Returns the wall clock seconds since 1970.
|
||||
*
|
||||
* For 64bit systems the fast access to tk->xtime_sec is preserved. On
|
||||
* 32bit systems the access must be protected with the sequence
|
||||
|
||||
@@ -538,7 +538,7 @@ config KPROBE_EVENTS
|
||||
config KPROBE_EVENTS_ON_NOTRACE
|
||||
bool "Do NOT protect notrace function from kprobe events"
|
||||
depends on KPROBE_EVENTS
|
||||
depends on KPROBES_ON_FTRACE
|
||||
depends on DYNAMIC_FTRACE
|
||||
default n
|
||||
help
|
||||
This is only for the developers who want to debug ftrace itself
|
||||
|
||||
@@ -96,9 +96,6 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
if (in_nmi()) /* not supported yet */
|
||||
return 1;
|
||||
|
||||
cant_sleep();
|
||||
|
||||
if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) {
|
||||
|
||||
@@ -394,7 +394,6 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
|
||||
}
|
||||
|
||||
if (t->ret_stack == NULL) {
|
||||
atomic_set(&t->tracing_graph_pause, 0);
|
||||
atomic_set(&t->trace_overrun, 0);
|
||||
t->curr_ret_stack = -1;
|
||||
t->curr_ret_depth = -1;
|
||||
@@ -489,7 +488,6 @@ static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
|
||||
static void
|
||||
graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
|
||||
{
|
||||
atomic_set(&t->tracing_graph_pause, 0);
|
||||
atomic_set(&t->trace_overrun, 0);
|
||||
t->ftrace_timestamp = 0;
|
||||
/* make curr_ret_stack visible before we add the ret_stack */
|
||||
|
||||
@@ -2745,7 +2745,7 @@ trace_event_buffer_lock_reserve(struct trace_buffer **current_rb,
|
||||
(entry = this_cpu_read(trace_buffered_event))) {
|
||||
/* Try to use the per cpu buffer first */
|
||||
val = this_cpu_inc_return(trace_buffered_event_cnt);
|
||||
if (val == 1) {
|
||||
if ((len < (PAGE_SIZE - sizeof(*entry))) && val == 1) {
|
||||
trace_event_setup(entry, type, flags, pc);
|
||||
entry->array[0] = len;
|
||||
return entry;
|
||||
|
||||
@@ -1212,7 +1212,8 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
|
||||
mutex_lock(&event_mutex);
|
||||
list_for_each_entry(file, &tr->events, list) {
|
||||
call = file->event_call;
|
||||
if (!trace_event_name(call) || !call->class || !call->class->reg)
|
||||
if ((call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) ||
|
||||
!trace_event_name(call) || !call->class || !call->class->reg)
|
||||
continue;
|
||||
|
||||
if (system && strcmp(call->class->system, system->name) != 0)
|
||||
|
||||
@@ -562,6 +562,8 @@ static int __irqsoff_tracer_init(struct trace_array *tr)
|
||||
/* non overwrite screws up the latency tracers */
|
||||
set_tracer_flag(tr, TRACE_ITER_OVERWRITE, 1);
|
||||
set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, 1);
|
||||
/* without pause, we will produce garbage if another latency occurs */
|
||||
set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, 1);
|
||||
|
||||
tr->max_latency = 0;
|
||||
irqsoff_trace = tr;
|
||||
@@ -583,11 +585,13 @@ static void __irqsoff_tracer_reset(struct trace_array *tr)
|
||||
{
|
||||
int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
|
||||
int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
|
||||
int pause_flag = save_flags & TRACE_ITER_PAUSE_ON_TRACE;
|
||||
|
||||
stop_irqsoff_tracer(tr, is_graph(tr));
|
||||
|
||||
set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, lat_flag);
|
||||
set_tracer_flag(tr, TRACE_ITER_OVERWRITE, overwrite_flag);
|
||||
set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, pause_flag);
|
||||
ftrace_reset_array_ops(tr);
|
||||
|
||||
irqsoff_busy = false;
|
||||
|
||||
@@ -221,9 +221,9 @@ bool trace_kprobe_on_func_entry(struct trace_event_call *call)
|
||||
{
|
||||
struct trace_kprobe *tk = trace_kprobe_primary_from_call(call);
|
||||
|
||||
return tk ? kprobe_on_func_entry(tk->rp.kp.addr,
|
||||
return tk ? (kprobe_on_func_entry(tk->rp.kp.addr,
|
||||
tk->rp.kp.addr ? NULL : tk->rp.kp.symbol_name,
|
||||
tk->rp.kp.addr ? 0 : tk->rp.kp.offset) : false;
|
||||
tk->rp.kp.addr ? 0 : tk->rp.kp.offset) == 0) : false;
|
||||
}
|
||||
|
||||
bool trace_kprobe_error_injectable(struct trace_event_call *call)
|
||||
@@ -434,7 +434,7 @@ static int disable_trace_kprobe(struct trace_event_call *call,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_KPROBES_ON_FTRACE) && \
|
||||
#if defined(CONFIG_DYNAMIC_FTRACE) && \
|
||||
!defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE)
|
||||
static bool __within_notrace_func(unsigned long addr)
|
||||
{
|
||||
@@ -828,9 +828,11 @@ static int trace_kprobe_create(int argc, const char *argv[])
|
||||
}
|
||||
if (is_return)
|
||||
flags |= TPARG_FL_RETURN;
|
||||
if (kprobe_on_func_entry(NULL, symbol, offset))
|
||||
ret = kprobe_on_func_entry(NULL, symbol, offset);
|
||||
if (ret == 0)
|
||||
flags |= TPARG_FL_FENTRY;
|
||||
if (offset && is_return && !(flags & TPARG_FL_FENTRY)) {
|
||||
/* Defer the ENOENT case until register kprobe */
|
||||
if (ret == -EINVAL && is_return) {
|
||||
trace_probe_log_err(0, BAD_RETPROBE);
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
+13
-9
@@ -1848,12 +1848,6 @@ static void worker_attach_to_pool(struct worker *worker,
|
||||
{
|
||||
mutex_lock(&wq_pool_attach_mutex);
|
||||
|
||||
/*
|
||||
* set_cpus_allowed_ptr() will fail if the cpumask doesn't have any
|
||||
* online CPUs. It'll be re-applied when any of the CPUs come up.
|
||||
*/
|
||||
set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
|
||||
|
||||
/*
|
||||
* The wq_pool_attach_mutex ensures %POOL_DISASSOCIATED remains
|
||||
* stable across this function. See the comments above the flag
|
||||
@@ -1861,6 +1855,11 @@ static void worker_attach_to_pool(struct worker *worker,
|
||||
*/
|
||||
if (pool->flags & POOL_DISASSOCIATED)
|
||||
worker->flags |= WORKER_UNBOUND;
|
||||
else
|
||||
kthread_set_per_cpu(worker->task, pool->cpu);
|
||||
|
||||
if (worker->rescue_wq)
|
||||
set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
|
||||
|
||||
list_add_tail(&worker->node, &pool->workers);
|
||||
worker->pool = pool;
|
||||
@@ -1883,6 +1882,7 @@ static void worker_detach_from_pool(struct worker *worker)
|
||||
|
||||
mutex_lock(&wq_pool_attach_mutex);
|
||||
|
||||
kthread_set_per_cpu(worker->task, -1);
|
||||
list_del(&worker->node);
|
||||
worker->pool = NULL;
|
||||
|
||||
@@ -4919,8 +4919,10 @@ static void unbind_workers(int cpu)
|
||||
|
||||
raw_spin_unlock_irq(&pool->lock);
|
||||
|
||||
for_each_pool_worker(worker, pool)
|
||||
WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_active_mask) < 0);
|
||||
for_each_pool_worker(worker, pool) {
|
||||
kthread_set_per_cpu(worker->task, -1);
|
||||
WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task, cpu_possible_mask) < 0);
|
||||
}
|
||||
|
||||
mutex_unlock(&wq_pool_attach_mutex);
|
||||
|
||||
@@ -4972,9 +4974,11 @@ static void rebind_workers(struct worker_pool *pool)
|
||||
* of all workers first and then clear UNBOUND. As we're called
|
||||
* from CPU_ONLINE, the following shouldn't fail.
|
||||
*/
|
||||
for_each_pool_worker(worker, pool)
|
||||
for_each_pool_worker(worker, pool) {
|
||||
kthread_set_per_cpu(worker->task, pool->cpu);
|
||||
WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task,
|
||||
pool->attrs->cpumask) < 0);
|
||||
}
|
||||
|
||||
raw_spin_lock_irq(&pool->lock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user