From ca8bc055fc73791a0e720f9f3e76ff2c45e6de42 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 20 Jul 2023 19:50:32 +0200 Subject: [PATCH] 4.19-stable patches added patches: workqueue-clean-up-work_-constant-types-clarify-masking.patch --- queue-4.19/series | 1 + ...work_-constant-types-clarify-masking.patch | 140 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 queue-4.19/workqueue-clean-up-work_-constant-types-clarify-masking.patch diff --git a/queue-4.19/series b/queue-4.19/series index 39c30d4a5c7..cf0d3b36314 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -135,6 +135,7 @@ netfilter-nf_tables-fix-scheduling-while-atomic-splat.patch netfilter-conntrack-avoid-nf_ct_helper_hash-uses-after-free.patch netfilter-nf_tables-prevent-oob-access-in-nft_byteorder_eval.patch net-lan743x-don-t-sleep-in-atomic-context.patch +workqueue-clean-up-work_-constant-types-clarify-masking.patch net-mvneta-fix-txq_map-in-case-of-txq_number-1.patch vrf-increment-icmp6inmsgs-on-the-original-netdev.patch icmp6-fix-null-ptr-deref-of-ip6_null_entry-rt6i_idev.patch diff --git a/queue-4.19/workqueue-clean-up-work_-constant-types-clarify-masking.patch b/queue-4.19/workqueue-clean-up-work_-constant-types-clarify-masking.patch new file mode 100644 index 00000000000..3d6a67fa0d2 --- /dev/null +++ b/queue-4.19/workqueue-clean-up-work_-constant-types-clarify-masking.patch @@ -0,0 +1,140 @@ +From afa4bb778e48d79e4a642ed41e3b4e0de7489a6c Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 23 Jun 2023 12:08:14 -0700 +Subject: workqueue: clean up WORK_* constant types, clarify masking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Linus Torvalds + +commit afa4bb778e48d79e4a642ed41e3b4e0de7489a6c upstream. + +Dave Airlie reports that gcc-13.1.1 has started complaining about some +of the workqueue code in 32-bit arm builds: + + kernel/workqueue.c: In function ‘get_work_pwq’: + kernel/workqueue.c:713:24: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] + 713 | return (void *)(data & WORK_STRUCT_WQ_DATA_MASK); + | ^ + [ ... a couple of other cases ... ] + +and while it's not immediately clear exactly why gcc started complaining +about it now, I suspect it's some C23-induced enum type handlign fixup in +gcc-13 is the cause. + +Whatever the reason for starting to complain, the code and data types +are indeed disgusting enough that the complaint is warranted. + +The wq code ends up creating various "helper constants" (like that +WORK_STRUCT_WQ_DATA_MASK) using an enum type, which is all kinds of +confused. The mask needs to be 'unsigned long', not some unspecified +enum type. + +To make matters worse, the actual "mask and cast to a pointer" is +repeated a couple of times, and the cast isn't even always done to the +right pointer, but - as the error case above - to a 'void *' with then +the compiler finishing the job. + +That's now how we roll in the kernel. + +So create the masks using the proper types rather than some ambiguous +enumeration, and use a nice helper that actually does the type +conversion in one well-defined place. + +Incidentally, this magically makes clang generate better code. That, +admittedly, is really just a sign of clang having been seriously +confused before, and cleaning up the typing unconfuses the compiler too. + +Reported-by: Dave Airlie +Link: https://lore.kernel.org/lkml/CAPM=9twNnV4zMCvrPkw3H-ajZOH-01JVh_kDrxdPYQErz8ZTdA@mail.gmail.com/ +Cc: Arnd Bergmann +Cc: Tejun Heo +Cc: Nick Desaulniers +Cc: Nathan Chancellor +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/workqueue.h | 15 ++++++++------- + kernel/workqueue.c | 13 ++++++++----- + 2 files changed, 16 insertions(+), 12 deletions(-) + +--- a/include/linux/workqueue.h ++++ b/include/linux/workqueue.h +@@ -73,7 +73,6 @@ enum { + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, + + __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, +- WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), + + /* + * When a work item is off queue, its high bits point to the last +@@ -84,12 +83,6 @@ enum { + WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, + WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT, + WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31, +- WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1, +- +- /* convenience constants */ +- WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, +- WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, +- WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT, + + /* bit mask for work_busy() return values */ + WORK_BUSY_PENDING = 1 << 0, +@@ -99,6 +92,14 @@ enum { + WORKER_DESC_LEN = 24, + }; + ++/* Convenience constants - of type 'unsigned long', not 'enum'! */ ++#define WORK_OFFQ_CANCELING (1ul << __WORK_OFFQ_CANCELING) ++#define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1) ++#define WORK_STRUCT_NO_POOL (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT) ++ ++#define WORK_STRUCT_FLAG_MASK ((1ul << WORK_STRUCT_FLAG_BITS) - 1) ++#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) ++ + struct work_struct { + atomic_long_t data; + struct list_head entry; +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -680,12 +680,17 @@ static void clear_work_data(struct work_ + set_work_data(work, WORK_STRUCT_NO_POOL, 0); + } + ++static inline struct pool_workqueue *work_struct_pwq(unsigned long data) ++{ ++ return (struct pool_workqueue *)(data & WORK_STRUCT_WQ_DATA_MASK); ++} ++ + static struct pool_workqueue *get_work_pwq(struct work_struct *work) + { + unsigned long data = atomic_long_read(&work->data); + + if (data & WORK_STRUCT_PWQ) +- return (void *)(data & WORK_STRUCT_WQ_DATA_MASK); ++ return work_struct_pwq(data); + else + return NULL; + } +@@ -713,8 +718,7 @@ static struct worker_pool *get_work_pool + assert_rcu_or_pool_mutex(); + + if (data & WORK_STRUCT_PWQ) +- return ((struct pool_workqueue *) +- (data & WORK_STRUCT_WQ_DATA_MASK))->pool; ++ return work_struct_pwq(data)->pool; + + pool_id = data >> WORK_OFFQ_POOL_SHIFT; + if (pool_id == WORK_OFFQ_POOL_NONE) +@@ -735,8 +739,7 @@ static int get_work_pool_id(struct work_ + unsigned long data = atomic_long_read(&work->data); + + if (data & WORK_STRUCT_PWQ) +- return ((struct pool_workqueue *) +- (data & WORK_STRUCT_WQ_DATA_MASK))->pool->id; ++ return work_struct_pwq(data)->pool->id; + + return data >> WORK_OFFQ_POOL_SHIFT; + } -- 2.47.3