In platform with multi NUMA nodes, there is no ordering guarantee with the workqueue created by calling alloc_ordered_workqueue().
Add member ordered_pwq in structure workqueue_struct, used to hold the first choice of pwq, in order to avoid breaking its ordering guarantee under enqueueing work in different NUMA nodes. Signed-off-by: Libin <huawei.li...@huawei.com> --- kernel/workqueue.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 29b7985..42c6c29 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -249,6 +249,7 @@ struct workqueue_struct { struct workqueue_attrs *unbound_attrs; /* WQ: only for unbound wqs */ struct pool_workqueue *dfl_pwq; /* WQ: only for unbound wqs */ + struct pool_workqueue *ordered_pwq; /* WQ: only for ordered wqs */ #ifdef CONFIG_SYSFS struct wq_device *wq_dev; /* I: for sysfs interface */ @@ -1326,10 +1327,19 @@ retry: /* pwq which will be used unless @work is executing elsewhere */ if (!(wq->flags & WQ_UNBOUND)) - pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); - else - pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu)); + pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); + else { + pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu)); + if (wq->flags & __WQ_ORDERED) { + mutex_lock(&wq->mutex); + if (wq->ordered_pwq == NULL) + wq->ordered_pwq = pwq; + else + pwq = wq->ordered_pwq; + mutex_unlock(&wq->mutex); + } + } /* * If @work was previously on a different pool, it might still be * running there, in which case the work needs to be queued on that -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/