8475 lines · 239.9 KB · C
RawDownload
			cpumask_copy(wq_requested_unbound_cpumask, cpumask);		mutex_unlock(&wq_pool_mutex);	} 	return ret;} static ssize_t __wq_cpumask_show(struct device *dev,		struct device_attribute *attr, char *buf, cpumask_var_t mask){	int written; 	mutex_lock(&wq_pool_mutex);	written = scnprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));	mutex_unlock(&wq_pool_mutex); 	return written;} static ssize_t cpumask_requested_show(struct device *dev,		struct device_attribute *attr, char *buf){	return __wq_cpumask_show(dev, attr, buf, wq_requested_unbound_cpumask);}static DEVICE_ATTR_RO(cpumask_requested); static ssize_t cpumask_isolated_show(struct device *dev,		struct device_attribute *attr, char *buf){	return __wq_cpumask_show(dev, attr, buf, wq_isolated_cpumask);}static DEVICE_ATTR_RO(cpumask_isolated); static ssize_t cpumask_show(struct device *dev,		struct device_attribute *attr, char *buf){	return __wq_cpumask_show(dev, attr, buf, wq_unbound_cpumask);} static ssize_t cpumask_store(struct device *dev,		struct device_attribute *attr, const char *buf, size_t count){	cpumask_var_t cpumask;	int ret; 	if (!zalloc_cpumask_var(&cpumask, GFP_KERNEL))		return -ENOMEM; 	ret = cpumask_parse(buf, cpumask);	if (!ret)		ret = workqueue_set_unbound_cpumask(cpumask); 	free_cpumask_var(cpumask);	return ret ? ret : count;}static DEVICE_ATTR_RW(cpumask); static struct attribute *wq_sysfs_cpumask_attrs[] = {	&dev_attr_cpumask.attr,	&dev_attr_cpumask_requested.attr,	&dev_attr_cpumask_isolated.attr,	NULL,};ATTRIBUTE_GROUPS(wq_sysfs_cpumask); static int __init wq_sysfs_init(void){	return subsys_virtual_register(&wq_subsys, wq_sysfs_cpumask_groups);}core_initcall(wq_sysfs_init); static void wq_device_release(struct device *dev){	struct wq_device *wq_dev = container_of(dev, struct wq_device, dev); 	kfree(wq_dev);} /** * workqueue_sysfs_register - make a workqueue visible in sysfs * @wq: the workqueue to register * * Expose @wq in sysfs under /sys/bus/workqueue/devices. * alloc_workqueue*() automatically calls this function if WQ_SYSFS is set * which is the preferred method. * * Workqueue user should use this function directly iff it wants to apply * workqueue_attrs before making the workqueue visible in sysfs; otherwise, * apply_workqueue_attrs() may race against userland updating the * attributes. * * Return: 0 on success, -errno on failure. */int workqueue_sysfs_register(struct workqueue_struct *wq){	struct wq_device *wq_dev;	int ret; 	wq->wq_dev = wq_dev = kzalloc_obj(*wq_dev);	if (!wq_dev)		return -ENOMEM; 	wq_dev->wq = wq;	wq_dev->dev.bus = &wq_subsys;	wq_dev->dev.release = wq_device_release;	dev_set_name(&wq_dev->dev, "%s", wq->name); 	/*	 * unbound_attrs are created separately.  Suppress uevent until	 * everything is ready.	 */	dev_set_uevent_suppress(&wq_dev->dev, true); 	ret = device_register(&wq_dev->dev);	if (ret) {		put_device(&wq_dev->dev);		wq->wq_dev = NULL;		return ret;	} 	if (wq->flags & WQ_UNBOUND) {		struct device_attribute *attr; 		for (attr = wq_sysfs_unbound_attrs; attr->attr.name; attr++) {			ret = device_create_file(&wq_dev->dev, attr);			if (ret) {				device_unregister(&wq_dev->dev);				wq->wq_dev = NULL;				return ret;			}		}	} 	dev_set_uevent_suppress(&wq_dev->dev, false);	kobject_uevent(&wq_dev->dev.kobj, KOBJ_ADD);	return 0;} /** * workqueue_sysfs_unregister - undo workqueue_sysfs_register() * @wq: the workqueue to unregister * * If @wq is registered to sysfs by workqueue_sysfs_register(), unregister. */static void workqueue_sysfs_unregister(struct workqueue_struct *wq){	struct wq_device *wq_dev = wq->wq_dev; 	if (!wq->wq_dev)		return; 	wq->wq_dev = NULL;	device_unregister(&wq_dev->dev);}#else	/* CONFIG_SYSFS */static void workqueue_sysfs_unregister(struct workqueue_struct *wq)	{ }#endif	/* CONFIG_SYSFS */ /* * Workqueue watchdog. * * Stall may be caused by various bugs - missing WQ_MEM_RECLAIM, illegal * flush dependency, a concurrency managed work item which stays RUNNING * indefinitely.  Workqueue stalls can be very difficult to debug as the * usual warning mechanisms don't trigger and internal workqueue state is * largely opaque. * * Workqueue watchdog monitors all worker pools periodically and dumps * state if some pools failed to make forward progress for a while where * forward progress is defined as the first item on ->worklist changing. * * This mechanism is controlled through the kernel parameter * "workqueue.watchdog_thresh" which can be updated at runtime through the * corresponding sysfs parameter file. */#ifdef CONFIG_WQ_WATCHDOG static unsigned long wq_watchdog_thresh = 30;static struct timer_list wq_watchdog_timer; static unsigned long wq_watchdog_touched = INITIAL_JIFFIES;static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES; static unsigned int wq_panic_on_stall = CONFIG_BOOTPARAM_WQ_STALL_PANIC;module_param_named(panic_on_stall, wq_panic_on_stall, uint, 0644); static unsigned int wq_panic_on_stall_time;module_param_named(panic_on_stall_time, wq_panic_on_stall_time, uint, 0644);MODULE_PARM_DESC(panic_on_stall_time, "Panic if stall exceeds this many seconds (0=disabled)"); /* * Show workers that might prevent the processing of pending work items. * A busy worker that is not running on the CPU (e.g. sleeping in * wait_event_idle() with PF_WQ_WORKER cleared) can stall the pool just as * effectively as a CPU-bound one, so dump every in-flight worker. */static void show_cpu_pool_busy_workers(struct worker_pool *pool){	struct worker *worker;	unsigned long irq_flags;	int bkt; 	raw_spin_lock_irqsave(&pool->lock, irq_flags); 	hash_for_each(pool->busy_hash, bkt, worker, hentry) {		/*		 * Defer printing to avoid deadlocks in console		 * drivers that queue work while holding locks		 * also taken in their write paths.		 */		printk_deferred_enter(); 		pr_info("pool %d:\n", pool->id);		sched_show_task(worker->task); 		printk_deferred_exit();	} 	raw_spin_unlock_irqrestore(&pool->lock, irq_flags);} static void show_cpu_pools_busy_workers(void){	struct worker_pool *pool;	int pi; 	pr_info("Showing backtraces of busy workers in stalled worker pools:\n"); 	rcu_read_lock(); 	for_each_pool(pool, pi) {		if (pool->cpu_stall)			show_cpu_pool_busy_workers(pool); 	} 	rcu_read_unlock();} /* * It triggers a panic in two scenarios: when the total number of stalls * exceeds a threshold, and when a stall lasts longer than * wq_panic_on_stall_time */static void panic_on_wq_watchdog(unsigned int stall_time_sec){	static unsigned int wq_stall; 	if (wq_panic_on_stall) {		wq_stall++;		if (wq_stall >= wq_panic_on_stall)			panic("workqueue: %u stall(s) exceeded threshold %u\n",			      wq_stall, wq_panic_on_stall);	} 	if (wq_panic_on_stall_time && stall_time_sec >= wq_panic_on_stall_time)		panic("workqueue: stall lasted %us, exceeding threshold %us\n",		      stall_time_sec, wq_panic_on_stall_time);} static void wq_watchdog_reset_touched(void){	int cpu; 	wq_watchdog_touched = jiffies;	for_each_possible_cpu(cpu)		per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;} static void wq_watchdog_timer_fn(struct timer_list *unused){	unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;	unsigned int max_stall_time = 0;	bool lockup_detected = false;	bool cpu_pool_stall = false;	unsigned long now = jiffies;	struct worker_pool *pool;	unsigned int stall_time;	int pi; 	if (!thresh)		return; 	for_each_pool(pool, pi) {		unsigned long pool_ts, touched, ts; 		pool->cpu_stall = false;		if (list_empty(&pool->worklist))			continue; 		/*		 * If a virtual machine is stopped by the host it can look to		 * the watchdog like a stall.		 */		kvm_check_and_clear_guest_paused(); 		/* get the latest of pool and touched timestamps */		if (pool->cpu >= 0)			touched = READ_ONCE(per_cpu(wq_watchdog_touched_cpu, pool->cpu));		else			touched = READ_ONCE(wq_watchdog_touched);		pool_ts = READ_ONCE(pool->last_progress_ts); 		if (time_after(pool_ts, touched))			ts = pool_ts;		else			ts = touched; 		/*		 * Did we stall?		 *		 * Do a lockless check first to do not disturb the system.		 *		 * Prevent false positives by double checking the timestamp		 * under pool->lock. The lock makes sure that the check reads		 * an updated pool->last_progress_ts when this CPU saw		 * an already updated pool->worklist above. It seems better		 * than adding another barrier into __queue_work() which		 * is a hotter path.		 */		if (time_after(now, ts + thresh)) {			scoped_guard(raw_spinlock_irqsave, &pool->lock) {				pool_ts = pool->last_progress_ts;				if (time_after(pool_ts, touched))					ts = pool_ts;				else					ts = touched;			}			if (!time_after(now, ts + thresh))				continue; 			lockup_detected = true;			stall_time = jiffies_to_msecs(now - pool_ts) / 1000;			max_stall_time = max(max_stall_time, stall_time);			if (pool->cpu >= 0 && !(pool->flags & POOL_BH)) {				pool->cpu_stall = true;				cpu_pool_stall = true;			}			pr_emerg("BUG: workqueue lockup - pool");			pr_cont_pool_info(pool);			pr_cont(" stuck for %us!\n", stall_time);		}	} 	if (lockup_detected)		show_all_workqueues(); 	if (cpu_pool_stall)		show_cpu_pools_busy_workers(); 	if (lockup_detected)		panic_on_wq_watchdog(max_stall_time); 	wq_watchdog_reset_touched();	mod_timer(&wq_watchdog_timer, jiffies + thresh);} notrace void wq_watchdog_touch(int cpu){	unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;	unsigned long touch_ts = READ_ONCE(wq_watchdog_touched);	unsigned long now = jiffies; 	if (cpu >= 0)		per_cpu(wq_watchdog_touched_cpu, cpu) = now;	else		WARN_ONCE(1, "%s should be called with valid CPU", __func__); 	/* Don't unnecessarily store to global cacheline */	if (time_after(now, touch_ts + thresh / 4))		WRITE_ONCE(wq_watchdog_touched, jiffies);} static void wq_watchdog_set_thresh(unsigned long thresh){	wq_watchdog_thresh = 0;	timer_delete_sync(&wq_watchdog_timer); 	if (thresh) {		wq_watchdog_thresh = thresh;		wq_watchdog_reset_touched();		mod_timer(&wq_watchdog_timer, jiffies + thresh * HZ);	}} static int wq_watchdog_param_set_thresh(const char *val,					const struct kernel_param *kp){	unsigned long thresh;	int ret; 	ret = kstrtoul(val, 0, &thresh);	if (ret)		return ret; 	if (system_percpu_wq)		wq_watchdog_set_thresh(thresh);	else		wq_watchdog_thresh = thresh; 	return 0;} static const struct kernel_param_ops wq_watchdog_thresh_ops = {	.set	= wq_watchdog_param_set_thresh,	.get	= param_get_ulong,}; module_param_cb(watchdog_thresh, &wq_watchdog_thresh_ops, &wq_watchdog_thresh,		0644); static void wq_watchdog_init(void){	timer_setup(&wq_watchdog_timer, wq_watchdog_timer_fn, TIMER_DEFERRABLE);	wq_watchdog_set_thresh(wq_watchdog_thresh);} #else	/* CONFIG_WQ_WATCHDOG */ static inline void wq_watchdog_init(void) { } #endif	/* CONFIG_WQ_WATCHDOG */ static void bh_pool_kick_normal(struct irq_work *irq_work){	raise_softirq_irqoff(TASKLET_SOFTIRQ);} static void bh_pool_kick_highpri(struct irq_work *irq_work){	raise_softirq_irqoff(HI_SOFTIRQ);} static void __init restrict_unbound_cpumask(const char *name, const struct cpumask *mask){	if (!cpumask_intersects(wq_unbound_cpumask, mask)) {		pr_warn("workqueue: Restricting unbound_cpumask (%*pb) with %s (%*pb) leaves no CPU, ignoring\n",			cpumask_pr_args(wq_unbound_cpumask), name, cpumask_pr_args(mask));		return;	} 	cpumask_and(wq_unbound_cpumask, wq_unbound_cpumask, mask);} static void __init init_cpu_worker_pool(struct worker_pool *pool, int cpu, int nice){	BUG_ON(init_worker_pool(pool));	pool->cpu = cpu;	cpumask_copy(pool->attrs->cpumask, cpumask_of(cpu));	cpumask_copy(pool->attrs->__pod_cpumask, cpumask_of(cpu));	pool->attrs->nice = nice;	pool->attrs->affn_strict = true;	pool->node = cpu_to_node(cpu); 	/* alloc pool ID */	mutex_lock(&wq_pool_mutex);	BUG_ON(worker_pool_assign_id(pool));	mutex_unlock(&wq_pool_mutex);} /** * workqueue_init_early - early init for workqueue subsystem * * This is the first step of three-staged workqueue subsystem initialization and * invoked as soon as the bare basics - memory allocation, cpumasks and idr are * up. It sets up all the data structures and system workqueues and allows early * boot code to create workqueues and queue/cancel work items. Actual work item * execution starts only after kthreads can be created and scheduled right * before early initcalls. */void __init workqueue_init_early(void){	struct wq_pod_type *pt = &wq_pod_types[WQ_AFFN_SYSTEM];	int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };	void (*irq_work_fns[NR_STD_WORKER_POOLS])(struct irq_work *) =		{ bh_pool_kick_normal, bh_pool_kick_highpri };	int i, cpu; 	BUILD_BUG_ON(__alignof__(struct pool_workqueue) < __alignof__(long long)); 	BUG_ON(!alloc_cpumask_var(&wq_online_cpumask, GFP_KERNEL));	BUG_ON(!alloc_cpumask_var(&wq_unbound_cpumask, GFP_KERNEL));	BUG_ON(!alloc_cpumask_var(&wq_requested_unbound_cpumask, GFP_KERNEL));	BUG_ON(!zalloc_cpumask_var(&wq_isolated_cpumask, GFP_KERNEL)); 	cpumask_copy(wq_online_cpumask, cpu_online_mask);	cpumask_copy(wq_unbound_cpumask, cpu_possible_mask);	restrict_unbound_cpumask("HK_TYPE_DOMAIN", housekeeping_cpumask(HK_TYPE_DOMAIN));	if (!cpumask_empty(&wq_cmdline_cpumask))		restrict_unbound_cpumask("workqueue.unbound_cpus", &wq_cmdline_cpumask); 	cpumask_copy(wq_requested_unbound_cpumask, wq_unbound_cpumask);	cpumask_andnot(wq_isolated_cpumask, cpu_possible_mask,						housekeeping_cpumask(HK_TYPE_DOMAIN));	pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC); 	unbound_wq_update_pwq_attrs_buf = alloc_workqueue_attrs();	BUG_ON(!unbound_wq_update_pwq_attrs_buf); 	/*

Lines 7501–8000 of 8475. Previous lines