Factor out pool_workqueue linking and installation into numa_pwq_tbl[] from apply_workqueue_attrs() into numa_pwq_tbl_install(). link_pwq() is made safe to call multiple times. numa_pwq_tbl_install() links the pwq, installs it into numa_pwq_tbl[] at the specified node and returns the old entry. @last_pwq is removed from link_pwq() as the return value of the new function can be used instead. This is to prepare for NUMA affinity support for unbound workqueues.
Showing the changes to kernel/workqueue.c (1 of 1 file). Show all
Unified · Split
| @@ -3639,24 +3639,26 @@ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq, · 3638 unmodified lines | ||
| 3639 | 3639 | pwq->flush_color = -1; |
| 3640 | 3640 | pwq->refcnt = 1; |
| 3641 | 3641 | INIT_LIST_HEAD(&pwq->delayed_works); |
| 3642 | + INIT_LIST_HEAD(&pwq->pwqs_node); | |
| 3642 | 3643 | INIT_LIST_HEAD(&pwq->mayday_node); |
| 3643 | 3644 | INIT_WORK(&pwq->unbound_release_work, pwq_unbound_release_workfn); |
| 3644 | 3645 | } |
| 3645 | 3646 | |
| 3646 | 3647 | /* sync @pwq with the current state of its associated wq and link it */ |
| 3647 | −static void link_pwq(struct pool_workqueue *pwq, | |
| 3648 | − struct pool_workqueue **p_last_pwq) | |
| 3648 | +static void link_pwq(struct pool_workqueue *pwq) | |
| 3649 | 3649 | { |
| 3650 | 3650 | struct workqueue_struct *wq = pwq->wq; |
| 3651 | 3651 | |
| 3652 | 3652 | lockdep_assert_held(&wq->mutex); |
| 3653 | 3653 | |
| 3654 | + /* may be called multiple times, ignore if already linked */ | |
| 3655 | + if (!list_empty(&pwq->pwqs_node)) | |
| 3656 | + return; | |
| 3657 | + | |
| 3654 | 3658 | /* |
| 3655 | 3659 | * Set the matching work_color. This is synchronized with |
| 3656 | 3660 | * wq->mutex to avoid confusing flush_workqueue(). |
| 3657 | 3661 | */ |
| 3658 | − if (p_last_pwq) | |
| 3659 | − *p_last_pwq = first_pwq(wq); | |
| 3660 | 3662 | pwq->work_color = wq->work_color; |
| 3661 | 3663 | |
| 3662 | 3664 | /* sync max_active to the current setting */ |
| @@ -3689,6 +3691,23 @@ static struct pool_workqueue *alloc_unbound_pwq(struct workqueue_struct *wq, · 26 unmodified lines | ||
| 3689 | 3691 | return pwq; |
| 3690 | 3692 | } |
| 3691 | 3693 | |
| 3694 | +/* install @pwq into @wq's numa_pwq_tbl[] for @node and return the old pwq */ | |
| 3695 | +static struct pool_workqueue *numa_pwq_tbl_install(struct workqueue_struct *wq, | |
| 3696 | + int node, | |
| 3697 | + struct pool_workqueue *pwq) | |
| 3698 | +{ | |
| 3699 | + struct pool_workqueue *old_pwq; | |
| 3700 | + | |
| 3701 | + lockdep_assert_held(&wq->mutex); | |
| 3702 | + | |
| 3703 | + /* link_pwq() can handle duplicate calls */ | |
| 3704 | + link_pwq(pwq); | |
| 3705 | + | |
| 3706 | + old_pwq = rcu_access_pointer(wq->numa_pwq_tbl[node]); | |
| 3707 | + rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq); | |
| 3708 | + return old_pwq; | |
| 3709 | +} | |
| 3710 | + | |
| 3692 | 3711 | /** |
| 3693 | 3712 | * apply_workqueue_attrs - apply new workqueue_attrs to an unbound workqueue |
| 3694 | 3713 | * @wq: the target workqueue |
| @@ -3707,7 +3726,7 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 12 unmodified lines | ||
| 3707 | 3726 | const struct workqueue_attrs *attrs) |
| 3708 | 3727 | { |
| 3709 | 3728 | struct workqueue_attrs *new_attrs; |
| 3710 | − struct pool_workqueue *pwq, *last_pwq; | |
| 3729 | + struct pool_workqueue *pwq, *last_pwq = NULL; | |
| 3711 | 3730 | int node, ret; |
| 3712 | 3731 | |
| 3713 | 3732 | /* only unbound workqueues can change attributes */ |
| @@ -3734,11 +3753,9 @@ int apply_workqueue_attrs(struct workqueue_struct *wq, · 20 unmodified lines | ||
| 3734 | 3753 | |
| 3735 | 3754 | mutex_lock(&wq->mutex); |
| 3736 | 3755 | |
| 3737 | − link_pwq(pwq, &last_pwq); | |
| 3738 | − | |
| 3739 | 3756 | copy_workqueue_attrs(wq->unbound_attrs, new_attrs); |
| 3740 | 3757 | for_each_node(node) |
| 3741 | − rcu_assign_pointer(wq->numa_pwq_tbl[node], pwq); | |
| 3758 | + last_pwq = numa_pwq_tbl_install(wq, node, pwq); | |
| 3742 | 3759 | |
| 3743 | 3760 | mutex_unlock(&wq->mutex); |
| 3744 | 3761 | |
| @@ -3778,7 +3795,7 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 33 unmodified lines | ||
| 3778 | 3795 | init_pwq(pwq, wq, &cpu_pools[highpri]); |
| 3779 | 3796 | |
| 3780 | 3797 | mutex_lock(&wq->mutex); |
| 3781 | − link_pwq(pwq, NULL); | |
| 3798 | + link_pwq(pwq); | |
| 3782 | 3799 | mutex_unlock(&wq->mutex); |
| 3783 | 3800 | } |
| 3784 | 3801 | return 0; |