@@ -5108,6 +5108,19 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq,
5108
5108
return pwq ;
5109
5109
}
5110
5110
5111
+ static void apply_wqattrs_lock (void )
5112
+ {
5113
+ /* CPUs should stay stable across pwq creations and installations */
5114
+ cpus_read_lock ();
5115
+ mutex_lock (& wq_pool_mutex );
5116
+ }
5117
+
5118
+ static void apply_wqattrs_unlock (void )
5119
+ {
5120
+ mutex_unlock (& wq_pool_mutex );
5121
+ cpus_read_unlock ();
5122
+ }
5123
+
5111
5124
/**
5112
5125
* wq_calc_pod_cpumask - calculate a wq_attrs' cpumask for a pod
5113
5126
* @attrs: the wq_attrs of the default pwq of the target workqueue
@@ -5419,6 +5432,9 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
5419
5432
bool highpri = wq -> flags & WQ_HIGHPRI ;
5420
5433
int cpu , ret ;
5421
5434
5435
+ lockdep_assert_cpus_held ();
5436
+ lockdep_assert_held (& wq_pool_mutex );
5437
+
5422
5438
wq -> cpu_pwq = alloc_percpu (struct pool_workqueue * );
5423
5439
if (!wq -> cpu_pwq )
5424
5440
goto enomem ;
@@ -5452,20 +5468,18 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
5452
5468
return 0 ;
5453
5469
}
5454
5470
5455
- cpus_read_lock ();
5456
5471
if (wq -> flags & __WQ_ORDERED ) {
5457
5472
struct pool_workqueue * dfl_pwq ;
5458
5473
5459
- ret = apply_workqueue_attrs (wq , ordered_wq_attrs [highpri ]);
5474
+ ret = apply_workqueue_attrs_locked (wq , ordered_wq_attrs [highpri ]);
5460
5475
/* there should only be single pwq for ordering guarantee */
5461
5476
dfl_pwq = rcu_access_pointer (wq -> dfl_pwq );
5462
5477
WARN (!ret && (wq -> pwqs .next != & dfl_pwq -> pwqs_node ||
5463
5478
wq -> pwqs .prev != & dfl_pwq -> pwqs_node ),
5464
5479
"ordering guarantee broken for workqueue %s\n" , wq -> name );
5465
5480
} else {
5466
- ret = apply_workqueue_attrs (wq , unbound_std_wq_attrs [highpri ]);
5481
+ ret = apply_workqueue_attrs_locked (wq , unbound_std_wq_attrs [highpri ]);
5467
5482
}
5468
- cpus_read_unlock ();
5469
5483
5470
5484
return ret ;
5471
5485
@@ -5672,23 +5686,23 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
5672
5686
goto err_unreg_lockdep ;
5673
5687
}
5674
5688
5675
- if (alloc_and_link_pwqs (wq ) < 0 )
5676
- goto err_free_node_nr_active ;
5677
-
5678
5689
/*
5679
- * wq_pool_mutex protects global freeze state and workqueues list.
5680
- * Grab it, adjust max_active and add the new @wq to workqueues
5681
- * list .
5690
+ * wq_pool_mutex protects the workqueues list, allocations of PWQs,
5691
+ * and the global freeze state. alloc_and_link_pwqs() also requires
5692
+ * cpus_read_lock() for PWQs' affinities .
5682
5693
*/
5683
- mutex_lock (& wq_pool_mutex );
5694
+ apply_wqattrs_lock ();
5695
+
5696
+ if (alloc_and_link_pwqs (wq ) < 0 )
5697
+ goto err_unlock_free_node_nr_active ;
5684
5698
5685
5699
mutex_lock (& wq -> mutex );
5686
5700
wq_adjust_max_active (wq );
5687
5701
mutex_unlock (& wq -> mutex );
5688
5702
5689
5703
list_add_tail_rcu (& wq -> list , & workqueues );
5690
5704
5691
- mutex_unlock ( & wq_pool_mutex );
5705
+ apply_wqattrs_unlock ( );
5692
5706
5693
5707
if (wq_online && init_rescuer (wq ) < 0 )
5694
5708
goto err_destroy ;
@@ -5698,7 +5712,8 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
5698
5712
5699
5713
return wq ;
5700
5714
5701
- err_free_node_nr_active :
5715
+ err_unlock_free_node_nr_active :
5716
+ apply_wqattrs_unlock ();
5702
5717
/*
5703
5718
* Failed alloc_and_link_pwqs() may leave pending pwq->release_work,
5704
5719
* flushing the pwq_release_worker ensures that the pwq_release_workfn()
@@ -6987,19 +7002,6 @@ static struct attribute *wq_sysfs_attrs[] = {
6987
7002
};
6988
7003
ATTRIBUTE_GROUPS (wq_sysfs );
6989
7004
6990
- static void apply_wqattrs_lock (void )
6991
- {
6992
- /* CPUs should stay stable across pwq creations and installations */
6993
- cpus_read_lock ();
6994
- mutex_lock (& wq_pool_mutex );
6995
- }
6996
-
6997
- static void apply_wqattrs_unlock (void )
6998
- {
6999
- mutex_unlock (& wq_pool_mutex );
7000
- cpus_read_unlock ();
7001
- }
7002
-
7003
7005
static ssize_t wq_nice_show (struct device * dev , struct device_attribute * attr ,
7004
7006
char * buf )
7005
7007
{
0 commit comments