6039 lines · 165.7 KB · C
RawDownload
} static void apply_wqattrs_unlock(void){	mutex_unlock(&wq_pool_mutex);	put_online_cpus();} static int apply_workqueue_attrs_locked(struct workqueue_struct *wq,					const struct workqueue_attrs *attrs){	struct apply_wqattrs_ctx *ctx; 	/* only unbound workqueues can change attributes */	if (WARN_ON(!(wq->flags & WQ_UNBOUND)))		return -EINVAL; 	/* creating multiple pwqs breaks ordering guarantee */	if (!list_empty(&wq->pwqs)) {		if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))			return -EINVAL; 		wq->flags &= ~__WQ_ORDERED;	} 	ctx = apply_wqattrs_prepare(wq, attrs);	if (!ctx)		return -ENOMEM; 	/* the ctx has been prepared successfully, let's commit it */	apply_wqattrs_commit(ctx);	apply_wqattrs_cleanup(ctx); 	return 0;} /** * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue * @wq: the target workqueue * @attrs: the workqueue_attrs to apply, allocated with alloc_workqueue_attrs() * * Apply @attrs to an unbound workqueue @wq.  Unless disabled, on NUMA * machines, this function maps a separate pwq to each NUMA node with * possibles CPUs in @attrs->cpumask so that work items are affine to the * NUMA node it was issued on.  Older pwqs are released as in-flight work * items finish.  Note that a work item which repeatedly requeues itself * back-to-back will stay on its current pwq. * * Performs GFP_KERNEL allocations. * * Assumes caller has CPU hotplug read exclusion, i.e. get_online_cpus(). * * Return: 0 on success and -errno on failure. */int apply_workqueue_attrs(struct workqueue_struct *wq,			  const struct workqueue_attrs *attrs){	int ret; 	lockdep_assert_cpus_held(); 	mutex_lock(&wq_pool_mutex);	ret = apply_workqueue_attrs_locked(wq, attrs);	mutex_unlock(&wq_pool_mutex); 	return ret;} /** * wq_update_unbound_numa - update NUMA affinity of a wq for CPU hot[un]plug * @wq: the target workqueue * @cpu: the CPU coming up or going down * @online: whether @cpu is coming up or going down * * This function is to be called from %CPU_DOWN_PREPARE, %CPU_ONLINE and * %CPU_DOWN_FAILED.  @cpu is being hot[un]plugged, update NUMA affinity of * @wq accordingly. * * If NUMA affinity can't be adjusted due to memory allocation failure, it * falls back to @wq->dfl_pwq which may not be optimal but is always * correct. * * Note that when the last allowed CPU of a NUMA node goes offline for a * workqueue with a cpumask spanning multiple nodes, the workers which were * already executing the work items for the workqueue will lose their CPU * affinity and may execute on any CPU.  This is similar to how per-cpu * workqueues behave on CPU_DOWN.  If a workqueue user wants strict * affinity, it's the user's responsibility to flush the work item from * CPU_DOWN_PREPARE. */static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,				   bool online){	int node = cpu_to_node(cpu);	int cpu_off = online ? -1 : cpu;	struct pool_workqueue *old_pwq = NULL, *pwq;	struct workqueue_attrs *target_attrs;	cpumask_t *cpumask; 	lockdep_assert_held(&wq_pool_mutex); 	if (!wq_numa_enabled || !(wq->flags & WQ_UNBOUND) ||	    wq->unbound_attrs->no_numa)		return; 	/*	 * We don't wanna alloc/free wq_attrs for each wq for each CPU.	 * Let's use a preallocated one.  The following buf is protected by	 * CPU hotplug exclusion.	 */	target_attrs = wq_update_unbound_numa_attrs_buf;	cpumask = target_attrs->cpumask; 	copy_workqueue_attrs(target_attrs, wq->unbound_attrs);	pwq = unbound_pwq_by_node(wq, node); 	/*	 * Let's determine what needs to be done.  If the target cpumask is	 * different from the default pwq's, we need to compare it to @pwq's	 * and create a new one if they don't match.  If the target cpumask	 * equals the default pwq's, the default pwq should be used.	 */	if (wq_calc_node_cpumask(wq->dfl_pwq->pool->attrs, node, cpu_off, cpumask)) {		if (cpumask_equal(cpumask, pwq->pool->attrs->cpumask))			return;	} else {		goto use_dfl_pwq;	} 	/* create a new pwq */	pwq = alloc_unbound_pwq(wq, target_attrs);	if (!pwq) {		pr_warn("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",			wq->name);		goto use_dfl_pwq;	} 	/* Install the new pwq. */	mutex_lock(&wq->mutex);	old_pwq = numa_pwq_tbl_install(wq, node, pwq);	goto out_unlock; use_dfl_pwq:	mutex_lock(&wq->mutex);	raw_spin_lock_irq(&wq->dfl_pwq->pool->lock);	get_pwq(wq->dfl_pwq);	raw_spin_unlock_irq(&wq->dfl_pwq->pool->lock);	old_pwq = numa_pwq_tbl_install(wq, node, wq->dfl_pwq);out_unlock:	mutex_unlock(&wq->mutex);	put_pwq_unlocked(old_pwq);} static int alloc_and_link_pwqs(struct workqueue_struct *wq){	bool highpri = wq->flags & WQ_HIGHPRI;	int cpu, ret; 	if (!(wq->flags & WQ_UNBOUND)) {		wq->cpu_pwqs = alloc_percpu(struct pool_workqueue);		if (!wq->cpu_pwqs)			return -ENOMEM; 		for_each_possible_cpu(cpu) {			struct pool_workqueue *pwq =				per_cpu_ptr(wq->cpu_pwqs, cpu);			struct worker_pool *cpu_pools =				per_cpu(cpu_worker_pools, cpu); 			init_pwq(pwq, wq, &cpu_pools[highpri]); 			mutex_lock(&wq->mutex);			link_pwq(pwq);			mutex_unlock(&wq->mutex);		}		return 0;	} 	get_online_cpus();	if (wq->flags & __WQ_ORDERED) {		ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);		/* there should only be single pwq for ordering guarantee */		WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||			      wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),		     "ordering guarantee broken for workqueue %s\n", wq->name);	} else {		ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);	}	put_online_cpus(); 	return ret;} static int wq_clamp_max_active(int max_active, unsigned int flags,			       const char *name){	int lim = flags & WQ_UNBOUND ? WQ_UNBOUND_MAX_ACTIVE : WQ_MAX_ACTIVE; 	if (max_active < 1 || max_active > lim)		pr_warn("workqueue: max_active %d requested for %s is out of range, clamping between %d and %d\n",			max_active, name, 1, lim); 	return clamp_val(max_active, 1, lim);} /* * Workqueues which may be used during memory reclaim should have a rescuer * to guarantee forward progress. */static int init_rescuer(struct workqueue_struct *wq){	struct worker *rescuer;	int ret; 	if (!(wq->flags & WQ_MEM_RECLAIM))		return 0; 	rescuer = alloc_worker(NUMA_NO_NODE);	if (!rescuer)		return -ENOMEM; 	rescuer->rescue_wq = wq;	rescuer->task = kthread_create(rescuer_thread, rescuer, "%s", wq->name);	if (IS_ERR(rescuer->task)) {		ret = PTR_ERR(rescuer->task);		kfree(rescuer);		return ret;	} 	wq->rescuer = rescuer;	kthread_bind_mask(rescuer->task, cpu_possible_mask);	wake_up_process(rescuer->task); 	return 0;} __printf(1, 4)struct workqueue_struct *alloc_workqueue(const char *fmt,					 unsigned int flags,					 int max_active, ...){	size_t tbl_size = 0;	va_list args;	struct workqueue_struct *wq;	struct pool_workqueue *pwq; 	/*	 * Unbound && max_active == 1 used to imply ordered, which is no	 * longer the case on NUMA machines due to per-node pools.  While	 * alloc_ordered_workqueue() is the right way to create an ordered	 * workqueue, keep the previous behavior to avoid subtle breakages	 * on NUMA.	 */	if ((flags & WQ_UNBOUND) && max_active == 1)		flags |= __WQ_ORDERED; 	/* see the comment above the definition of WQ_POWER_EFFICIENT */	if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient)		flags |= WQ_UNBOUND; 	/* allocate wq and format name */	if (flags & WQ_UNBOUND)		tbl_size = nr_node_ids * sizeof(wq->numa_pwq_tbl[0]); 	wq = kzalloc(sizeof(*wq) + tbl_size, GFP_KERNEL);	if (!wq)		return NULL; 	if (flags & WQ_UNBOUND) {		wq->unbound_attrs = alloc_workqueue_attrs();		if (!wq->unbound_attrs)			goto err_free_wq;	} 	va_start(args, max_active);	vsnprintf(wq->name, sizeof(wq->name), fmt, args);	va_end(args); 	max_active = max_active ?: WQ_DFL_ACTIVE;	max_active = wq_clamp_max_active(max_active, flags, wq->name); 	/* init wq */	wq->flags = flags;	wq->saved_max_active = max_active;	mutex_init(&wq->mutex);	atomic_set(&wq->nr_pwqs_to_flush, 0);	INIT_LIST_HEAD(&wq->pwqs);	INIT_LIST_HEAD(&wq->flusher_queue);	INIT_LIST_HEAD(&wq->flusher_overflow);	INIT_LIST_HEAD(&wq->maydays); 	wq_init_lockdep(wq);	INIT_LIST_HEAD(&wq->list); 	if (alloc_and_link_pwqs(wq) < 0)		goto err_unreg_lockdep; 	if (wq_online && init_rescuer(wq) < 0)		goto err_destroy; 	if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))		goto err_destroy; 	/*	 * wq_pool_mutex protects global freeze state and workqueues list.	 * Grab it, adjust max_active and add the new @wq to workqueues	 * list.	 */	mutex_lock(&wq_pool_mutex); 	mutex_lock(&wq->mutex);	for_each_pwq(pwq, wq)		pwq_adjust_max_active(pwq);	mutex_unlock(&wq->mutex); 	list_add_tail_rcu(&wq->list, &workqueues); 	mutex_unlock(&wq_pool_mutex); 	return wq; err_unreg_lockdep:	wq_unregister_lockdep(wq);	wq_free_lockdep(wq);err_free_wq:	free_workqueue_attrs(wq->unbound_attrs);	kfree(wq);	return NULL;err_destroy:	destroy_workqueue(wq);	return NULL;}EXPORT_SYMBOL_GPL(alloc_workqueue); static bool pwq_busy(struct pool_workqueue *pwq){	int i; 	for (i = 0; i < WORK_NR_COLORS; i++)		if (pwq->nr_in_flight[i])			return true; 	if ((pwq != pwq->wq->dfl_pwq) && (pwq->refcnt > 1))		return true;	if (pwq->nr_active || !list_empty(&pwq->delayed_works))		return true; 	return false;} /** * destroy_workqueue - safely terminate a workqueue * @wq: target workqueue * * Safely destroy a workqueue. All work currently pending will be done first. */void destroy_workqueue(struct workqueue_struct *wq){	struct pool_workqueue *pwq;	int node; 	/*	 * Remove it from sysfs first so that sanity check failure doesn't	 * lead to sysfs name conflicts.	 */	workqueue_sysfs_unregister(wq); 	/* drain it before proceeding with destruction */	drain_workqueue(wq); 	/* kill rescuer, if sanity checks fail, leave it w/o rescuer */	if (wq->rescuer) {		struct worker *rescuer = wq->rescuer; 		/* this prevents new queueing */		raw_spin_lock_irq(&wq_mayday_lock);		wq->rescuer = NULL;		raw_spin_unlock_irq(&wq_mayday_lock); 		/* rescuer will empty maydays list before exiting */		kthread_stop(rescuer->task);		kfree(rescuer);	} 	/*	 * Sanity checks - grab all the locks so that we wait for all	 * in-flight operations which may do put_pwq().	 */	mutex_lock(&wq_pool_mutex);	mutex_lock(&wq->mutex);	for_each_pwq(pwq, wq) {		raw_spin_lock_irq(&pwq->pool->lock);		if (WARN_ON(pwq_busy(pwq))) {			pr_warn("%s: %s has the following busy pwq\n",				__func__, wq->name);			show_pwq(pwq);			raw_spin_unlock_irq(&pwq->pool->lock);			mutex_unlock(&wq->mutex);			mutex_unlock(&wq_pool_mutex);			show_workqueue_state();			return;		}		raw_spin_unlock_irq(&pwq->pool->lock);	}	mutex_unlock(&wq->mutex); 	/*	 * wq list is used to freeze wq, remove from list after	 * flushing is complete in case freeze races us.	 */	list_del_rcu(&wq->list);	mutex_unlock(&wq_pool_mutex); 	if (!(wq->flags & WQ_UNBOUND)) {		wq_unregister_lockdep(wq);		/*		 * The base ref is never dropped on per-cpu pwqs.  Directly		 * schedule RCU free.		 */		call_rcu(&wq->rcu, rcu_free_wq);	} else {		/*		 * We're the sole accessor of @wq at this point.  Directly		 * access numa_pwq_tbl[] and dfl_pwq to put the base refs.		 * @wq will be freed when the last pwq is released.		 */		for_each_node(node) {			pwq = rcu_access_pointer(wq->numa_pwq_tbl[node]);			RCU_INIT_POINTER(wq->numa_pwq_tbl[node], NULL);			put_pwq_unlocked(pwq);		} 		/*		 * Put dfl_pwq.  @wq may be freed any time after dfl_pwq is		 * put.  Don't access it afterwards.		 */		pwq = wq->dfl_pwq;		wq->dfl_pwq = NULL;		put_pwq_unlocked(pwq);	}}EXPORT_SYMBOL_GPL(destroy_workqueue); /** * workqueue_set_max_active - adjust max_active of a workqueue * @wq: target workqueue * @max_active: new max_active value. * * Set max_active of @wq to @max_active. * * CONTEXT: * Don't call from IRQ context. */void workqueue_set_max_active(struct workqueue_struct *wq, int max_active){	struct pool_workqueue *pwq; 	/* disallow meddling with max_active for ordered workqueues */	if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))		return; 	max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); 	mutex_lock(&wq->mutex); 	wq->flags &= ~__WQ_ORDERED;	wq->saved_max_active = max_active; 	for_each_pwq(pwq, wq)		pwq_adjust_max_active(pwq); 	mutex_unlock(&wq->mutex);}EXPORT_SYMBOL_GPL(workqueue_set_max_active); /** * current_work - retrieve %current task's work struct * * Determine if %current task is a workqueue worker and what it's working on. * Useful to find out the context that the %current task is running in. * * Return: work struct if %current task is a workqueue worker, %NULL otherwise. */struct work_struct *current_work(void){	struct worker *worker = current_wq_worker(); 	return worker ? worker->current_work : NULL;}EXPORT_SYMBOL(current_work); /** * current_is_workqueue_rescuer - is %current workqueue rescuer? * * Determine whether %current is a workqueue rescuer.  Can be used from * work functions to determine whether it's being run off the rescuer task. * * Return: %true if %current is a workqueue rescuer. %false otherwise. */bool current_is_workqueue_rescuer(void)

Lines 4001–4500 of 6039. Previous lines