From: Greg Kroah-Hartman Date: Thu, 20 Jul 2023 17:50:23 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v5.15.121~99 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f3c6cefd6192e4b4607f39c02b068ca2f4a0972e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: workqueue-clean-up-work_-constant-types-clarify-masking.patch --- diff --git a/queue-4.14/series b/queue-4.14/series index 9f44e177d62..27fdd51c774 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -89,6 +89,7 @@ netfilter-nf_tables-add-nft_trans_prepare_error-to-deal-with-bound-set-chain.pat netfilter-nf_tables-unbind-non-anonymous-set-if-rule-construction-fails.patch netfilter-conntrack-avoid-nf_ct_helper_hash-uses-after-free.patch netfilter-nf_tables-prevent-oob-access-in-nft_byteorder_eval.patch +workqueue-clean-up-work_-constant-types-clarify-masking.patch net-mvneta-fix-txq_map-in-case-of-txq_number-1.patch udp6-fix-udp6_ehashfn-typo.patch ntb-idt-fix-error-handling-in-idt_pci_driver_init.patch diff --git a/queue-4.14/workqueue-clean-up-work_-constant-types-clarify-masking.patch b/queue-4.14/workqueue-clean-up-work_-constant-types-clarify-masking.patch new file mode 100644 index 00000000000..7e9dd1af056 --- /dev/null +++ b/queue-4.14/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 +@@ -72,7 +72,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 +@@ -83,12 +82,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, +@@ -98,6 +91,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 +@@ -682,12 +682,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; + } +@@ -715,8 +720,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) +@@ -737,8 +741,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; + }