diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/acct.c | 2 | ||||
| -rw-r--r-- | kernel/cgroup.c | 15 | ||||
| -rw-r--r-- | kernel/configs.c | 2 | ||||
| -rw-r--r-- | kernel/cpuset.c | 15 | ||||
| -rw-r--r-- | kernel/events/core.c | 8 | ||||
| -rw-r--r-- | kernel/exit.c | 2 | ||||
| -rw-r--r-- | kernel/fork.c | 5 | ||||
| -rw-r--r-- | kernel/futex.c | 46 | ||||
| -rw-r--r-- | kernel/irq/proc.c | 20 | ||||
| -rw-r--r-- | kernel/nsproxy.c | 6 | ||||
| -rw-r--r-- | kernel/pid.c | 1 | ||||
| -rw-r--r-- | kernel/pid_namespace.c | 2 | ||||
| -rw-r--r-- | kernel/printk.c | 80 | ||||
| -rw-r--r-- | kernel/profile.c | 6 | ||||
| -rw-r--r-- | kernel/sched/stats.c | 7 | ||||
| -rw-r--r-- | kernel/signal.c | 5 | ||||
| -rw-r--r-- | kernel/smpboot.c | 4 | ||||
| -rw-r--r-- | kernel/softirq.c | 21 | ||||
| -rw-r--r-- | kernel/stop_machine.c | 2 | ||||
| -rw-r--r-- | kernel/sys.c | 57 | ||||
| -rw-r--r-- | kernel/time/tick-broadcast.c | 3 | ||||
| -rw-r--r-- | kernel/trace/Kconfig | 24 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 86 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 6 | ||||
| -rw-r--r-- | kernel/trace/trace_irqsoff.c | 19 | ||||
| -rw-r--r-- | kernel/trace/trace_sched_wakeup.c | 18 | ||||
| -rw-r--r-- | kernel/user.c | 2 | ||||
| -rw-r--r-- | kernel/user_namespace.c | 6 | ||||
| -rw-r--r-- | kernel/utsname.c | 2 | ||||
| -rw-r--r-- | kernel/workqueue.c | 51 | 
31 files changed, 302 insertions, 225 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index b9bd7f098ee..85389fe2abd 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -543,6 +543,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,  	 * Kernel segment override to datasegment and write it  	 * to the accounting file.  	 */ +	file_start_write(file);  	fs = get_fs();  	set_fs(KERNEL_DS);  	/* @@ -554,6 +555,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,  			       sizeof(acct_t), &file->f_pos);  	current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;  	set_fs(fs); +	file_end_write(file);  out:  	revert_creds(orig_cred);  } diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a32f9432666..d5cffe80b46 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4769,7 +4769,7 @@ out:   */  /* TODO: Use a proper seq_file iterator */ -static int proc_cgroup_show(struct seq_file *m, void *v) +int proc_cgroup_show(struct seq_file *m, void *v)  {  	struct pid *pid;  	struct task_struct *tsk; @@ -4821,19 +4821,6 @@ out:  	return retval;  } -static int cgroup_open(struct inode *inode, struct file *file) -{ -	struct pid *pid = PROC_I(inode)->pid; -	return single_open(file, proc_cgroup_show, pid); -} - -const struct file_operations proc_cgroup_operations = { -	.open		= cgroup_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= single_release, -}; -  /* Display information about each subsystem and each hierarchy */  static int proc_cgroupstats_show(struct seq_file *m, void *v)  { diff --git a/kernel/configs.c b/kernel/configs.c index 42e8fa075ee..c18b1f1ae51 100644 --- a/kernel/configs.c +++ b/kernel/configs.c @@ -79,7 +79,7 @@ static int __init ikconfig_init(void)  	if (!entry)  		return -ENOMEM; -	entry->size = kernel_config_data_size; +	proc_set_size(entry, kernel_config_data_size);  	return 0;  } diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 4f9dfe43ecb..1b6f615be58 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2666,7 +2666,7 @@ void __cpuset_memory_pressure_bump(void)   *    and we take cpuset_mutex, keeping cpuset_attach() from changing it   *    anyway.   */ -static int proc_cpuset_show(struct seq_file *m, void *unused_v) +int proc_cpuset_show(struct seq_file *m, void *unused_v)  {  	struct pid *pid;  	struct task_struct *tsk; @@ -2700,19 +2700,6 @@ out_free:  out:  	return retval;  } - -static int cpuset_open(struct inode *inode, struct file *file) -{ -	struct pid *pid = PROC_I(inode)->pid; -	return single_open(file, proc_cpuset_show, pid); -} - -const struct file_operations proc_cpuset_operations = { -	.open		= cpuset_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= single_release, -};  #endif /* CONFIG_PROC_PID_CPUSET */  /* Display task mems_allowed in /proc/<pid>/status file. */ diff --git a/kernel/events/core.c b/kernel/events/core.c index b0cd86501c3..59412d037ee 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4434,12 +4434,15 @@ static void perf_event_task_event(struct perf_task_event *task_event)  			if (ctxn < 0)  				goto next;  			ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); +			if (ctx) +				perf_event_task_ctx(ctx, task_event);  		} -		if (ctx) -			perf_event_task_ctx(ctx, task_event);  next:  		put_cpu_ptr(pmu->pmu_cpu_context);  	} +	if (task_event->task_ctx) +		perf_event_task_ctx(task_event->task_ctx, task_event); +  	rcu_read_unlock();  } @@ -5647,6 +5650,7 @@ static void perf_swevent_init_hrtimer(struct perf_event *event)  		event->attr.sample_period = NSEC_PER_SEC / freq;  		hwc->sample_period = event->attr.sample_period;  		local64_set(&hwc->period_left, hwc->sample_period); +		hwc->last_period = hwc->sample_period;  		event->attr.freq = 0;  	}  } diff --git a/kernel/exit.c b/kernel/exit.c index 51e485ca993..cd9e9e799bd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -847,7 +847,7 @@ void do_exit(long code)  		exit_io_context(tsk);  	if (tsk->splice_pipe) -		__free_pipe_info(tsk->splice_pipe); +		free_pipe_info(tsk->splice_pipe);  	if (tsk->task_frag.page)  		put_page(tsk->task_frag.page); diff --git a/kernel/fork.c b/kernel/fork.c index 8d932b1c905..1766d324d5e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1141,6 +1141,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,  	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))  		return ERR_PTR(-EINVAL); +	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) +		return ERR_PTR(-EINVAL); +  	/*  	 * Thread groups must share signals as well, and detached threads  	 * can only be started up within the thread group. @@ -1807,7 +1810,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)  	 * If unsharing a user namespace must also unshare the thread.  	 */  	if (unshare_flags & CLONE_NEWUSER) -		unshare_flags |= CLONE_THREAD; +		unshare_flags |= CLONE_THREAD | CLONE_FS;  	/*  	 * If unsharing a pid namespace must also unshare the thread.  	 */ diff --git a/kernel/futex.c b/kernel/futex.c index f0090a993da..b26dcfc02c9 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -223,7 +223,8 @@ static void drop_futex_key_refs(union futex_key *key)   * @rw:		mapping needs to be read/write (values: VERIFY_READ,   *              VERIFY_WRITE)   * - * Returns a negative error code or 0 + * Return: a negative error code or 0 + *   * The key words are stored in *key on success.   *   * For shared mappings, it's (page->index, file_inode(vma->vm_file), @@ -705,9 +706,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,   *			be "current" except in the case of requeue pi.   * @set_waiters:	force setting the FUTEX_WAITERS bit (1) or not (0)   * - * Returns: - *  0 - ready to wait - *  1 - acquired the lock + * Return: + *  0 - ready to wait; + *  1 - acquired the lock;   * <0 - error   *   * The hb->lock and futex_key refs shall be held by the caller. @@ -1191,9 +1192,9 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,   * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.   * hb1 and hb2 must be held by the caller.   * - * Returns: - *  0 - failed to acquire the lock atomicly - *  1 - acquired the lock + * Return: + *  0 - failed to acquire the lock atomically; + *  1 - acquired the lock;   * <0 - error   */  static int futex_proxy_trylock_atomic(u32 __user *pifutex, @@ -1254,8 +1255,8 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,   * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire   * uaddr2 atomically on behalf of the top waiter.   * - * Returns: - * >=0 - on success, the number of tasks requeued or woken + * Return: + * >=0 - on success, the number of tasks requeued or woken;   *  <0 - on error   */  static int futex_requeue(u32 __user *uaddr1, unsigned int flags, @@ -1536,8 +1537,8 @@ static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)   * The q->lock_ptr must not be held by the caller. A call to unqueue_me() must   * be paired with exactly one earlier call to queue_me().   * - * Returns: - *   1 - if the futex_q was still queued (and we removed unqueued it) + * Return: + *   1 - if the futex_q was still queued (and we removed unqueued it);   *   0 - if the futex_q was already removed by the waking thread   */  static int unqueue_me(struct futex_q *q) @@ -1707,9 +1708,9 @@ static long futex_wait_restart(struct restart_block *restart);   * the pi_state owner as well as handle race conditions that may allow us to   * acquire the lock. Must be called with the hb lock held.   * - * Returns: - *  1 - success, lock taken - *  0 - success, lock not taken + * Return: + *  1 - success, lock taken; + *  0 - success, lock not taken;   * <0 - on error (-EFAULT)   */  static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) @@ -1824,8 +1825,8 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,   * Return with the hb lock held and a q.key reference on success, and unlocked   * with no q.key reference on failure.   * - * Returns: - *  0 - uaddr contains val and hb has been locked + * Return: + *  0 - uaddr contains val and hb has been locked;   * <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked   */  static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags, @@ -2203,9 +2204,9 @@ pi_faulted:   * the wakeup and return the appropriate error code to the caller.  Must be   * called with the hb lock held.   * - * Returns - *  0 - no early wakeup detected - * <0 - -ETIMEDOUT or -ERESTARTNOINTR + * Return: + *  0 = no early wakeup detected; + * <0 = -ETIMEDOUT or -ERESTARTNOINTR   */  static inline  int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, @@ -2247,7 +2248,6 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,   * @val:	the expected value of uaddr   * @abs_time:	absolute timeout   * @bitset:	32 bit wakeup bitset set by userspace, defaults to all - * @clockrt:	whether to use CLOCK_REALTIME (1) or CLOCK_MONOTONIC (0)   * @uaddr2:	the pi futex we will take prior to returning to user-space   *   * The caller will wait on uaddr and will be requeued by futex_requeue() to @@ -2258,7 +2258,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,   * there was a need to.   *   * We call schedule in futex_wait_queue_me() when we enqueue and return there - * via the following: + * via the following--   * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()   * 2) wakeup on uaddr2 after a requeue   * 3) signal @@ -2276,8 +2276,8 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,   *   * If 4 or 7, we cleanup and return with -ETIMEDOUT.   * - * Returns: - *  0 - On success + * Return: + *  0 - On success;   * <0 - On error   */  static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 397db02209e..19ed5c425c3 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -76,7 +76,7 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)  static ssize_t write_irq_affinity(int type, struct file *file,  		const char __user *buffer, size_t count, loff_t *pos)  { -	unsigned int irq = (int)(long)PDE(file_inode(file))->data; +	unsigned int irq = (int)(long)PDE_DATA(file_inode(file));  	cpumask_var_t new_value;  	int err; @@ -131,17 +131,17 @@ static ssize_t irq_affinity_list_proc_write(struct file *file,  static int irq_affinity_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, irq_affinity_proc_show, PDE(inode)->data); +	return single_open(file, irq_affinity_proc_show, PDE_DATA(inode));  }  static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, irq_affinity_list_proc_show, PDE(inode)->data); +	return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));  }  static int irq_affinity_hint_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, irq_affinity_hint_proc_show, PDE(inode)->data); +	return single_open(file, irq_affinity_hint_proc_show, PDE_DATA(inode));  }  static const struct file_operations irq_affinity_proc_fops = { @@ -212,7 +212,7 @@ out:  static int default_affinity_open(struct inode *inode, struct file *file)  { -	return single_open(file, default_affinity_show, PDE(inode)->data); +	return single_open(file, default_affinity_show, PDE_DATA(inode));  }  static const struct file_operations default_affinity_proc_fops = { @@ -233,7 +233,7 @@ static int irq_node_proc_show(struct seq_file *m, void *v)  static int irq_node_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, irq_node_proc_show, PDE(inode)->data); +	return single_open(file, irq_node_proc_show, PDE_DATA(inode));  }  static const struct file_operations irq_node_proc_fops = { @@ -256,7 +256,7 @@ static int irq_spurious_proc_show(struct seq_file *m, void *v)  static int irq_spurious_proc_open(struct inode *inode, struct file *file)  { -	return single_open(file, irq_spurious_proc_show, PDE(inode)->data); +	return single_open(file, irq_spurious_proc_show, PDE_DATA(inode));  }  static const struct file_operations irq_spurious_proc_fops = { @@ -366,11 +366,7 @@ void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)  void unregister_handler_proc(unsigned int irq, struct irqaction *action)  { -	if (action->dir) { -		struct irq_desc *desc = irq_to_desc(irq); - -		remove_proc_entry(action->dir->name, desc->dir); -	} +	proc_remove(action->dir);  }  static void register_default_affinity_proc(void) diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index afc0456f227..364ceab15f0 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -22,7 +22,7 @@  #include <linux/pid_namespace.h>  #include <net/net_namespace.h>  #include <linux/ipc_namespace.h> -#include <linux/proc_fs.h> +#include <linux/proc_ns.h>  #include <linux/file.h>  #include <linux/syscalls.h> @@ -241,7 +241,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)  	const struct proc_ns_operations *ops;  	struct task_struct *tsk = current;  	struct nsproxy *new_nsproxy; -	struct proc_inode *ei; +	struct proc_ns *ei;  	struct file *file;  	int err; @@ -250,7 +250,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)  		return PTR_ERR(file);  	err = -EINVAL; -	ei = PROC_I(file_inode(file)); +	ei = get_proc_ns(file_inode(file));  	ops = ei->ns_ops;  	if (nstype && (ops->type != nstype))  		goto out; diff --git a/kernel/pid.c b/kernel/pid.c index 047dc626463..686255e2c39 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -36,6 +36,7 @@  #include <linux/pid_namespace.h>  #include <linux/init_task.h>  #include <linux/syscalls.h> +#include <linux/proc_ns.h>  #include <linux/proc_fs.h>  #define pid_hashfn(nr, ns)	\ diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index c1c3dc1c602..4af28a84906 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -15,7 +15,7 @@  #include <linux/err.h>  #include <linux/acct.h>  #include <linux/slab.h> -#include <linux/proc_fs.h> +#include <linux/proc_ns.h>  #include <linux/reboot.h>  #include <linux/export.h> diff --git a/kernel/printk.c b/kernel/printk.c index 0b31715f335..abbdd9e2ac8 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -63,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)  #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */  #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ -DECLARE_WAIT_QUEUE_HEAD(log_wait); -  int console_printk[4] = {  	DEFAULT_CONSOLE_LOGLEVEL,	/* console_loglevel */  	DEFAULT_MESSAGE_LOGLEVEL,	/* default_message_loglevel */ @@ -224,6 +222,7 @@ struct log {  static DEFINE_RAW_SPINLOCK(logbuf_lock);  #ifdef CONFIG_PRINTK +DECLARE_WAIT_QUEUE_HEAD(log_wait);  /* the next printk record to read by syslog(READ) or /proc/kmsg */  static u64 syslog_seq;  static u32 syslog_idx; @@ -1957,45 +1956,6 @@ int is_console_locked(void)  	return console_locked;  } -/* - * Delayed printk version, for scheduler-internal messages: - */ -#define PRINTK_BUF_SIZE		512 - -#define PRINTK_PENDING_WAKEUP	0x01 -#define PRINTK_PENDING_SCHED	0x02 - -static DEFINE_PER_CPU(int, printk_pending); -static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); - -static void wake_up_klogd_work_func(struct irq_work *irq_work) -{ -	int pending = __this_cpu_xchg(printk_pending, 0); - -	if (pending & PRINTK_PENDING_SCHED) { -		char *buf = __get_cpu_var(printk_sched_buf); -		printk(KERN_WARNING "[sched_delayed] %s", buf); -	} - -	if (pending & PRINTK_PENDING_WAKEUP) -		wake_up_interruptible(&log_wait); -} - -static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { -	.func = wake_up_klogd_work_func, -	.flags = IRQ_WORK_LAZY, -}; - -void wake_up_klogd(void) -{ -	preempt_disable(); -	if (waitqueue_active(&log_wait)) { -		this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); -		irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); -	} -	preempt_enable(); -} -  static void console_cont_flush(char *text, size_t size)  {  	unsigned long flags; @@ -2458,6 +2418,44 @@ static int __init printk_late_init(void)  late_initcall(printk_late_init);  #if defined CONFIG_PRINTK +/* + * Delayed printk version, for scheduler-internal messages: + */ +#define PRINTK_BUF_SIZE		512 + +#define PRINTK_PENDING_WAKEUP	0x01 +#define PRINTK_PENDING_SCHED	0x02 + +static DEFINE_PER_CPU(int, printk_pending); +static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); + +static void wake_up_klogd_work_func(struct irq_work *irq_work) +{ +	int pending = __this_cpu_xchg(printk_pending, 0); + +	if (pending & PRINTK_PENDING_SCHED) { +		char *buf = __get_cpu_var(printk_sched_buf); +		printk(KERN_WARNING "[sched_delayed] %s", buf); +	} + +	if (pending & PRINTK_PENDING_WAKEUP) +		wake_up_interruptible(&log_wait); +} + +static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { +	.func = wake_up_klogd_work_func, +	.flags = IRQ_WORK_LAZY, +}; + +void wake_up_klogd(void) +{ +	preempt_disable(); +	if (waitqueue_active(&log_wait)) { +		this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); +		irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); +	} +	preempt_enable(); +}  int printk_sched(const char *fmt, ...)  { diff --git a/kernel/profile.c b/kernel/profile.c index dc3384ee874..0bf40073766 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -462,10 +462,10 @@ static const struct file_operations prof_cpu_mask_proc_fops = {  	.write		= prof_cpu_mask_proc_write,  }; -void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir) +void create_prof_cpu_mask(void)  {  	/* create /proc/irq/prof_cpu_mask */ -	proc_create("prof_cpu_mask", 0600, root_irq_dir, &prof_cpu_mask_proc_fops); +	proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_fops);  }  /* @@ -600,7 +600,7 @@ int __ref create_proc_profile(void) /* false positive from hotcpu_notifier */  			    NULL, &proc_profile_operations);  	if (!entry)  		return 0; -	entry->size = (1+prof_len) * sizeof(atomic_t); +	proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t));  	hotcpu_notifier(profile_cpu_callback, 0);  	return 0;  } diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c index e036eda1a9c..da98af347e8 100644 --- a/kernel/sched/stats.c +++ b/kernel/sched/stats.c @@ -130,16 +130,11 @@ static int schedstat_open(struct inode *inode, struct file *file)  	return seq_open(file, &schedstat_sops);  } -static int schedstat_release(struct inode *inode, struct file *file) -{ -	return 0; -}; -  static const struct file_operations proc_schedstat_operations = {  	.open    = schedstat_open,  	.read    = seq_read,  	.llseek  = seq_lseek, -	.release = schedstat_release, +	.release = seq_release,  };  static int __init proc_schedstat_init(void) diff --git a/kernel/signal.c b/kernel/signal.c index 2ec870a4c3c..dd72567767d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct *t, int force_default)  		if (force_default || ka->sa.sa_handler != SIG_IGN)  			ka->sa.sa_handler = SIG_DFL;  		ka->sa.sa_flags = 0; +#ifdef __ARCH_HAS_SA_RESTORER +		ka->sa.sa_restorer = NULL; +#endif  		sigemptyset(&ka->sa.sa_mask);  		ka++;  	} @@ -2682,7 +2685,7 @@ static int do_sigpending(void *set, unsigned long sigsetsize)  /**   *  sys_rt_sigpending - examine a pending signal that has been raised   *			while blocked - *  @set: stores pending signals + *  @uset: stores pending signals   *  @sigsetsize: size of sigset_t type or larger   */  SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) diff --git a/kernel/smpboot.c b/kernel/smpboot.c index b9bde572782..8eaed9aa9cf 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -131,7 +131,7 @@ static int smpboot_thread_fn(void *data)  			continue;  		} -		//BUG_ON(td->cpu != smp_processor_id()); +		BUG_ON(td->cpu != smp_processor_id());  		/* Check for state change setup */  		switch (td->status) { @@ -209,6 +209,8 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp  {  	struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); +	if (ht->pre_unpark) +		ht->pre_unpark(cpu);  	kthread_unpark(tsk);  } diff --git a/kernel/softirq.c b/kernel/softirq.c index b4d252fd195..14d7758074a 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -323,18 +323,10 @@ void irq_enter(void)  static inline void invoke_softirq(void)  { -	if (!force_irqthreads) { -#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED +	if (!force_irqthreads)  		__do_softirq(); -#else -		do_softirq(); -#endif -	} else { -		__local_bh_disable((unsigned long)__builtin_return_address(0), -				SOFTIRQ_OFFSET); +	else  		wakeup_softirqd(); -		__local_bh_enable(SOFTIRQ_OFFSET); -	}  }  /* @@ -342,9 +334,15 @@ static inline void invoke_softirq(void)   */  void irq_exit(void)  { +#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED +	local_irq_disable(); +#else +	WARN_ON_ONCE(!irqs_disabled()); +#endif +  	account_irq_exit_time(current);  	trace_hardirq_exit(); -	sub_preempt_count(IRQ_EXIT_OFFSET); +	sub_preempt_count(HARDIRQ_OFFSET);  	if (!in_interrupt() && local_softirq_pending())  		invoke_softirq(); @@ -354,7 +352,6 @@ void irq_exit(void)  		tick_nohz_irq_exit();  #endif  	rcu_irq_exit(); -	sched_preempt_enable_no_resched();  }  /* diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 95d178c62d5..c09f2955ae3 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = {  	.create			= cpu_stop_create,  	.setup			= cpu_stop_unpark,  	.park			= cpu_stop_park, -	.unpark			= cpu_stop_unpark, +	.pre_unpark		= cpu_stop_unpark,  	.selfparking		= true,  }; diff --git a/kernel/sys.c b/kernel/sys.c index 81f56445fba..39c9c4a2949 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2185,9 +2185,8 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,  char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; -static int __orderly_poweroff(void) +static int __orderly_poweroff(bool force)  { -	int argc;  	char **argv;  	static char *envp[] = {  		"HOME=/", @@ -2196,20 +2195,40 @@ static int __orderly_poweroff(void)  	};  	int ret; -	argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); -	if (argv == NULL) { +	argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL); +	if (argv) { +		ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); +		argv_free(argv); +	} else {  		printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", -		       __func__, poweroff_cmd); -		return -ENOMEM; +					 __func__, poweroff_cmd); +		ret = -ENOMEM;  	} -	ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC, -				      NULL, NULL, NULL); -	argv_free(argv); +	if (ret && force) { +		printk(KERN_WARNING "Failed to start orderly shutdown: " +					"forcing the issue\n"); +		/* +		 * I guess this should try to kick off some daemon to sync and +		 * poweroff asap.  Or not even bother syncing if we're doing an +		 * emergency shutdown? +		 */ +		emergency_sync(); +		kernel_power_off(); +	}  	return ret;  } +static bool poweroff_force; + +static void poweroff_work_func(struct work_struct *work) +{ +	__orderly_poweroff(poweroff_force); +} + +static DECLARE_WORK(poweroff_work, poweroff_work_func); +  /**   * orderly_poweroff - Trigger an orderly system poweroff   * @force: force poweroff if command execution fails @@ -2219,21 +2238,9 @@ static int __orderly_poweroff(void)   */  int orderly_poweroff(bool force)  { -	int ret = __orderly_poweroff(); - -	if (ret && force) { -		printk(KERN_WARNING "Failed to start orderly shutdown: " -		       "forcing the issue\n"); - -		/* -		 * I guess this should try to kick off some daemon to sync and -		 * poweroff asap.  Or not even bother syncing if we're doing an -		 * emergency shutdown? -		 */ -		emergency_sync(); -		kernel_power_off(); -	} - -	return ret; +	if (force) /* do not override the pending "true" */ +		poweroff_force = true; +	schedule_work(&poweroff_work); +	return 0;  }  EXPORT_SYMBOL_GPL(orderly_poweroff); diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 2fb8cb88df8..7f32fe0e52c 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -67,7 +67,8 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc)   */  int tick_check_broadcast_device(struct clock_event_device *dev)  { -	if ((tick_broadcast_device.evtdev && +	if ((dev->features & CLOCK_EVT_FEAT_DUMMY) || +	    (tick_broadcast_device.evtdev &&  	     tick_broadcast_device.evtdev->rating >= dev->rating) ||  	     (dev->features & CLOCK_EVT_FEAT_C3STOP))  		return 0; diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 192473b2279..fc382d6e276 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -414,24 +414,28 @@ config PROBE_EVENTS  	def_bool n  config DYNAMIC_FTRACE -	bool "enable/disable ftrace tracepoints dynamically" +	bool "enable/disable function tracing dynamically"  	depends on FUNCTION_TRACER  	depends on HAVE_DYNAMIC_FTRACE  	default y  	help -          This option will modify all the calls to ftrace dynamically -	  (will patch them out of the binary image and replace them -	  with a No-Op instruction) as they are called. A table is -	  created to dynamically enable them again. +	  This option will modify all the calls to function tracing +	  dynamically (will patch them out of the binary image and +	  replace them with a No-Op instruction) on boot up. During +	  compile time, a table is made of all the locations that ftrace +	  can function trace, and this table is linked into the kernel +	  image. When this is enabled, functions can be individually +	  enabled, and the functions not enabled will not affect +	  performance of the system. + +	  See the files in /sys/kernel/debug/tracing: +	    available_filter_functions +	    set_ftrace_filter +	    set_ftrace_notrace  	  This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but  	  otherwise has native performance as long as no tracing is active. -	  The changes to the code are done by a kernel thread that -	  wakes up once a second and checks to see if any ftrace calls -	  were made. If so, it runs stop_machine (stops all CPUS) -	  and modifies the code to jump over the call to ftrace. -  config DYNAMIC_FTRACE_WITH_REGS  	def_bool y  	depends on DYNAMIC_FTRACE diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index ab25b88aae5..6893d5a2bf0 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3104,8 +3104,8 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,  					continue;  			} -			hlist_del(&entry->node); -			call_rcu(&entry->rcu, ftrace_free_entry_rcu); +			hlist_del_rcu(&entry->node); +			call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu);  		}  	}  	__disable_ftrace_function_probe(); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c2e2c231037..4f1dade5698 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -704,7 +704,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)  void  update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)  { -	struct ring_buffer *buf = tr->buffer; +	struct ring_buffer *buf;  	if (trace_stop_count)  		return; @@ -719,6 +719,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)  	arch_spin_lock(&ftrace_max_lock); +	buf = tr->buffer;  	tr->buffer = max_tr.buffer;  	max_tr.buffer = buf; @@ -2400,6 +2401,27 @@ static void test_ftrace_alive(struct seq_file *m)  	seq_printf(m, "#          MAY BE MISSING FUNCTION EVENTS\n");  } +#ifdef CONFIG_TRACER_MAX_TRACE +static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) +{ +	if (iter->trace->allocated_snapshot) +		seq_printf(m, "#\n# * Snapshot is allocated *\n#\n"); +	else +		seq_printf(m, "#\n# * Snapshot is freed *\n#\n"); + +	seq_printf(m, "# Snapshot commands:\n"); +	seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n"); +	seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n"); +	seq_printf(m, "#                      Takes a snapshot of the main buffer.\n"); +	seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate)\n"); +	seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n"); +	seq_printf(m, "#                       is not a '0' or '1')\n"); +} +#else +/* Should never be called */ +static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { } +#endif +  static int s_show(struct seq_file *m, void *v)  {  	struct trace_iterator *iter = v; @@ -2411,7 +2433,9 @@ static int s_show(struct seq_file *m, void *v)  			seq_puts(m, "#\n");  			test_ftrace_alive(m);  		} -		if (iter->trace && iter->trace->print_header) +		if (iter->snapshot && trace_empty(iter)) +			print_snapshot_help(m, iter); +		else if (iter->trace && iter->trace->print_header)  			iter->trace->print_header(m);  		else  			trace_default_header(m); @@ -2857,11 +2881,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)  	return -EINVAL;  } -static void set_tracer_flags(unsigned int mask, int enabled) +/* Some tracers require overwrite to stay enabled */ +int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) +{ +	if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set) +		return -1; + +	return 0; +} + +int set_tracer_flag(unsigned int mask, int enabled)  {  	/* do nothing if flag is already set */  	if (!!(trace_flags & mask) == !!enabled) -		return; +		return 0; + +	/* Give the tracer a chance to approve the change */ +	if (current_trace->flag_changed) +		if (current_trace->flag_changed(current_trace, mask, !!enabled)) +			return -EINVAL;  	if (enabled)  		trace_flags |= mask; @@ -2871,18 +2909,24 @@ static void set_tracer_flags(unsigned int mask, int enabled)  	if (mask == TRACE_ITER_RECORD_CMD)  		trace_event_enable_cmd_record(enabled); -	if (mask == TRACE_ITER_OVERWRITE) +	if (mask == TRACE_ITER_OVERWRITE) {  		ring_buffer_change_overwrite(global_trace.buffer, enabled); +#ifdef CONFIG_TRACER_MAX_TRACE +		ring_buffer_change_overwrite(max_tr.buffer, enabled); +#endif +	}  	if (mask == TRACE_ITER_PRINTK)  		trace_printk_start_stop_comm(enabled); + +	return 0;  }  static int trace_set_options(char *option)  {  	char *cmp;  	int neg = 0; -	int ret = 0; +	int ret = -ENODEV;  	int i;  	cmp = strstrip(option); @@ -2892,19 +2936,20 @@ static int trace_set_options(char *option)  		cmp += 2;  	} +	mutex_lock(&trace_types_lock); +  	for (i = 0; trace_options[i]; i++) {  		if (strcmp(cmp, trace_options[i]) == 0) { -			set_tracer_flags(1 << i, !neg); +			ret = set_tracer_flag(1 << i, !neg);  			break;  		}  	}  	/* If no option could be set, test the specific tracer options */ -	if (!trace_options[i]) { -		mutex_lock(&trace_types_lock); +	if (!trace_options[i])  		ret = set_tracer_option(current_trace, cmp, neg); -		mutex_unlock(&trace_types_lock); -	} + +	mutex_unlock(&trace_types_lock);  	return ret;  } @@ -2914,6 +2959,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,  			size_t cnt, loff_t *ppos)  {  	char buf[64]; +	int ret;  	if (cnt >= sizeof(buf))  		return -EINVAL; @@ -2923,7 +2969,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,  	buf[cnt] = 0; -	trace_set_options(buf); +	ret = trace_set_options(buf); +	if (ret < 0) +		return ret;  	*ppos += cnt; @@ -3227,6 +3275,9 @@ static int tracing_set_tracer(const char *buf)  		goto out;  	trace_branch_disable(); + +	current_trace->enabled = false; +  	if (current_trace->reset)  		current_trace->reset(tr); @@ -3271,6 +3322,7 @@ static int tracing_set_tracer(const char *buf)  	}  	current_trace = t; +	current_trace->enabled = true;  	trace_branch_enable(tr);   out:  	mutex_unlock(&trace_types_lock); @@ -4144,8 +4196,6 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,  	default:  		if (current_trace->allocated_snapshot)  			tracing_reset_online_cpus(&max_tr); -		else -			ret = -EINVAL;  		break;  	} @@ -4759,7 +4809,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,  	if (val != 0 && val != 1)  		return -EINVAL; -	set_tracer_flags(1 << index, val); + +	mutex_lock(&trace_types_lock); +	ret = set_tracer_flag(1 << index, val); +	mutex_unlock(&trace_types_lock); + +	if (ret < 0) +		return ret;  	*ppos += cnt; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 57d7e5397d5..2081971367e 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -283,11 +283,15 @@ struct tracer {  	enum print_line_t	(*print_line)(struct trace_iterator *iter);  	/* If you handled the flag setting, return 0 */  	int			(*set_flag)(u32 old_flags, u32 bit, int set); +	/* Return 0 if OK with change, else return non-zero */ +	int			(*flag_changed)(struct tracer *tracer, +						u32 mask, int set);  	struct tracer		*next;  	struct tracer_flags	*flags;  	bool			print_max;  	bool			use_max_tr;  	bool			allocated_snapshot; +	bool			enabled;  }; @@ -943,6 +947,8 @@ extern const char *__stop___trace_bprintk_fmt[];  void trace_printk_init_buffers(void);  void trace_printk_start_comm(void); +int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set); +int set_tracer_flag(unsigned int mask, int enabled);  #undef FTRACE_ENTRY  #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter)	\ diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 713a2cac488..443b25b43b4 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -32,7 +32,7 @@ enum {  static int trace_type __read_mostly; -static int save_lat_flag; +static int save_flags;  static void stop_irqsoff_tracer(struct trace_array *tr, int graph);  static int start_irqsoff_tracer(struct trace_array *tr, int graph); @@ -558,8 +558,11 @@ static void stop_irqsoff_tracer(struct trace_array *tr, int graph)  static void __irqsoff_tracer_init(struct trace_array *tr)  { -	save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT; -	trace_flags |= TRACE_ITER_LATENCY_FMT; +	save_flags = trace_flags; + +	/* non overwrite screws up the latency tracers */ +	set_tracer_flag(TRACE_ITER_OVERWRITE, 1); +	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);  	tracing_max_latency = 0;  	irqsoff_trace = tr; @@ -573,10 +576,13 @@ static void __irqsoff_tracer_init(struct trace_array *tr)  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; +  	stop_irqsoff_tracer(tr, is_graph()); -	if (!save_lat_flag) -		trace_flags &= ~TRACE_ITER_LATENCY_FMT; +	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag); +	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);  }  static void irqsoff_tracer_start(struct trace_array *tr) @@ -609,6 +615,7 @@ static struct tracer irqsoff_tracer __read_mostly =  	.print_line     = irqsoff_print_line,  	.flags		= &tracer_flags,  	.set_flag	= irqsoff_set_flag, +	.flag_changed	= trace_keep_overwrite,  #ifdef CONFIG_FTRACE_SELFTEST  	.selftest    = trace_selftest_startup_irqsoff,  #endif @@ -642,6 +649,7 @@ static struct tracer preemptoff_tracer __read_mostly =  	.print_line     = irqsoff_print_line,  	.flags		= &tracer_flags,  	.set_flag	= irqsoff_set_flag, +	.flag_changed	= trace_keep_overwrite,  #ifdef CONFIG_FTRACE_SELFTEST  	.selftest    = trace_selftest_startup_preemptoff,  #endif @@ -677,6 +685,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =  	.print_line     = irqsoff_print_line,  	.flags		= &tracer_flags,  	.set_flag	= irqsoff_set_flag, +	.flag_changed	= trace_keep_overwrite,  #ifdef CONFIG_FTRACE_SELFTEST  	.selftest    = trace_selftest_startup_preemptirqsoff,  #endif diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 75aa97fbe1a..fde652c9a51 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -36,7 +36,7 @@ static void __wakeup_reset(struct trace_array *tr);  static int wakeup_graph_entry(struct ftrace_graph_ent *trace);  static void wakeup_graph_return(struct ftrace_graph_ret *trace); -static int save_lat_flag; +static int save_flags;  #define TRACE_DISPLAY_GRAPH     1 @@ -540,8 +540,11 @@ static void stop_wakeup_tracer(struct trace_array *tr)  static int __wakeup_tracer_init(struct trace_array *tr)  { -	save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT; -	trace_flags |= TRACE_ITER_LATENCY_FMT; +	save_flags = trace_flags; + +	/* non overwrite screws up the latency tracers */ +	set_tracer_flag(TRACE_ITER_OVERWRITE, 1); +	set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);  	tracing_max_latency = 0;  	wakeup_trace = tr; @@ -563,12 +566,15 @@ static int wakeup_rt_tracer_init(struct trace_array *tr)  static void wakeup_tracer_reset(struct trace_array *tr)  { +	int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; +	int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE; +  	stop_wakeup_tracer(tr);  	/* make sure we put back any tasks we are tracing */  	wakeup_reset(tr); -	if (!save_lat_flag) -		trace_flags &= ~TRACE_ITER_LATENCY_FMT; +	set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag); +	set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);  }  static void wakeup_tracer_start(struct trace_array *tr) @@ -594,6 +600,7 @@ static struct tracer wakeup_tracer __read_mostly =  	.print_line	= wakeup_print_line,  	.flags		= &tracer_flags,  	.set_flag	= wakeup_set_flag, +	.flag_changed	= trace_keep_overwrite,  #ifdef CONFIG_FTRACE_SELFTEST  	.selftest    = trace_selftest_startup_wakeup,  #endif @@ -615,6 +622,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =  	.print_line	= wakeup_print_line,  	.flags		= &tracer_flags,  	.set_flag	= wakeup_set_flag, +	.flag_changed	= trace_keep_overwrite,  #ifdef CONFIG_FTRACE_SELFTEST  	.selftest    = trace_selftest_startup_wakeup,  #endif diff --git a/kernel/user.c b/kernel/user.c index e81978e8c03..5bbb91988e6 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -16,7 +16,7 @@  #include <linux/interrupt.h>  #include <linux/export.h>  #include <linux/user_namespace.h> -#include <linux/proc_fs.h> +#include <linux/proc_ns.h>  /*   * userns count is 1 for root user, 1 for init_uts_ns, diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 8b650837083..51855f5f631 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -9,7 +9,7 @@  #include <linux/nsproxy.h>  #include <linux/slab.h>  #include <linux/user_namespace.h> -#include <linux/proc_fs.h> +#include <linux/proc_ns.h>  #include <linux/highuid.h>  #include <linux/cred.h>  #include <linux/securebits.h> @@ -21,6 +21,7 @@  #include <linux/uaccess.h>  #include <linux/ctype.h>  #include <linux/projid.h> +#include <linux/fs_struct.h>  static struct kmem_cache *user_ns_cachep __read_mostly; @@ -837,6 +838,9 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)  	if (atomic_read(¤t->mm->mm_users) > 1)  		return -EINVAL; +	if (current->fs->users != 1) +		return -EINVAL; +  	if (!ns_capable(user_ns, CAP_SYS_ADMIN))  		return -EPERM; diff --git a/kernel/utsname.c b/kernel/utsname.c index a47fc5de311..2fc8576efaa 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c @@ -15,7 +15,7 @@  #include <linux/err.h>  #include <linux/slab.h>  #include <linux/user_namespace.h> -#include <linux/proc_fs.h> +#include <linux/proc_ns.h>  static struct uts_namespace *create_uts_ns(void)  { diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 81f2457811e..b48cd597145 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -457,11 +457,12 @@ static int worker_pool_assign_id(struct worker_pool *pool)  	int ret;  	mutex_lock(&worker_pool_idr_mutex); -	idr_pre_get(&worker_pool_idr, GFP_KERNEL); -	ret = idr_get_new(&worker_pool_idr, pool, &pool->id); +	ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL); +	if (ret >= 0) +		pool->id = ret;  	mutex_unlock(&worker_pool_idr_mutex); -	return ret; +	return ret < 0 ? ret : 0;  }  /* @@ -3446,28 +3447,34 @@ static void wq_unbind_fn(struct work_struct *work)  		spin_unlock_irq(&pool->lock);  		mutex_unlock(&pool->assoc_mutex); -	} -	/* -	 * Call schedule() so that we cross rq->lock and thus can guarantee -	 * sched callbacks see the %WORKER_UNBOUND flag.  This is necessary -	 * as scheduler callbacks may be invoked from other cpus. -	 */ -	schedule(); +		/* +		 * Call schedule() so that we cross rq->lock and thus can +		 * guarantee sched callbacks see the %WORKER_UNBOUND flag. +		 * This is necessary as scheduler callbacks may be invoked +		 * from other cpus. +		 */ +		schedule(); -	/* -	 * Sched callbacks are disabled now.  Zap nr_running.  After this, -	 * nr_running stays zero and need_more_worker() and keep_working() -	 * are always true as long as the worklist is not empty.  Pools on -	 * @cpu now behave as unbound (in terms of concurrency management) -	 * pools which are served by workers tied to the CPU. -	 * -	 * On return from this function, the current worker would trigger -	 * unbound chain execution of pending work items if other workers -	 * didn't already. -	 */ -	for_each_std_worker_pool(pool, cpu) +		/* +		 * Sched callbacks are disabled now.  Zap nr_running. +		 * After this, nr_running stays zero and need_more_worker() +		 * and keep_working() are always true as long as the +		 * worklist is not empty.  This pool now behaves as an +		 * unbound (in terms of concurrency management) pool which +		 * are served by workers tied to the pool. +		 */  		atomic_set(&pool->nr_running, 0); + +		/* +		 * With concurrency management just turned off, a busy +		 * worker blocking could lead to lengthy stalls.  Kick off +		 * unbound chain execution of currently pending work items. +		 */ +		spin_lock_irq(&pool->lock); +		wake_up_worker(pool); +		spin_unlock_irq(&pool->lock); +	}  }  /*  |