FAILED: patch "[PATCH] fscontext: do not consume log entries when returning" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 72d271a7baa7062cb27e774ac37c5459c6d20e22
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025101543-quake-judicial-9e2e@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 72d271a7baa7062cb27e774ac37c5459c6d20e22 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <[email protected]>
Date: Thu, 7 Aug 2025 03:55:23 +1000
Subject: [PATCH] fscontext: do not consume log entries when returning
-EMSGSIZE
Userspace generally expects APIs that return -EMSGSIZE to allow for them to adjust their buffer size and retry the operation. However, the fscontext log would previously clear the message even in the -EMSGSIZE case.
Given that it is very cheap for us to check whether the buffer is too small before we remove the message from the ring buffer, let's just do that instead. While we're at it, refactor some fscontext_read() into a separate helper to make the ring buffer logic a bit easier to read.
fs/fsopen.c +38 -32
@@ -18,50 +18,56 @@#include "internal.h" #include "mount.h" +static inline const char *fetch_message_locked (struct fc_log *log,size_t len, +bool *need_free) +{ +const char *p; +int index; + +if (unlikely (log->head == log->tail)) +return ERR_PTR (-ENODATA ); + + index = log->tail & (ARRAY_SIZE (log->buffer) -1 ); + p = log->buffer[index]; +if (unlikely (strlen (p) > len)) +return ERR_PTR (-EMSGSIZE ); + + log->buffer[index] =NULL ; + *need_free = log->need_free & (1 << index); + log->need_free &= ~(1 << index); + log->tail++; + +return p; +} +/* * Allow the user to read back any error, warning or informational messages. +* Only one message is returned for each read(2) call. */ static ssize_t fscontext_read (struct file *file,char __user *_buf,size_t len,loff_t *pos) {struct fs_context *fc = file->private_data; -struct fc_log *log = fc->log.log; -unsigned int logsize =ARRAY_SIZE (log->buffer); -ssize_t ret; -char *p; +ssize_t err; + const char *p __free(kfree) = NULL, *message;bool need_free; -int index, n; +int n; - ret =mutex_lock_interruptible (&fc->uapi_mutex); -if (ret <0 ) -return ret; - -if (log->head == log->tail) { -mutex_unlock (&fc->uapi_mutex); -return -ENODATA ; - } - - index = log->tail & (logsize -1 ); - p = log->buffer[index]; - need_free = log->need_free & (1 << index); - log->buffer[index] =NULL ; - log->need_free &= ~(1 << index); - log->tail++; + err =mutex_lock_interruptible (&fc->uapi_mutex); +if (err <0 ) +return err; + message =fetch_message_locked (fc->log.log, len, &need_free);mutex_unlock (&fc->uapi_mutex); +if (IS_ERR (message)) +return PTR_ERR (message); - ret = -EMSGSIZE ; - n =strlen (p); -if (n > len) - goto err_free; - ret = -EFAULT ; -if (copy_to_user (_buf, p, n) !=0 ) - goto err_free; - ret = n; - -err_free:if (need_free) -kfree (p); -return ret; + p = message; + + n =strlen (message); +if (copy_to_user (_buf, message, n)) +return -EFAULT ; +return n; }static int fscontext_release (struct inode *inode,struct file *file)
Sasha Levin
maintainerPATCH 1/2 locking: Introduce __cleanup() based infrastructure
From: Peter Zijlstra <[email protected]>
[ Upstream commit 54da6a0924311c7cf5015533991e44fb8eb12773 ]
Use __attribute__((__cleanup__(func))) to build:
- simple auto-release pointers using __free()
- 'classes' with constructor and destructor semantics for scope-based resource management.
- lock guards based on the above classes.
--- drivers/dma/ioat/dma.c | 12 +- include/linux/cleanup.h | 171 ++++++++++++++++++++++++++++ include/linux/compiler-clang.h | 9 ++ include/linux/compiler_attributes.h | 6 + include/linux/device.h | 7 ++ include/linux/file.h | 6 + include/linux/irqflags.h | 7 ++ include/linux/mutex.h | 4 + include/linux/percpu.h | 4 + include/linux/preempt.h | 47 ++++++++ include/linux/rcupdate.h | 3 + include/linux/rwsem.h | 8 ++ include/linux/sched/task.h | 2 + include/linux/slab.h | 3 + include/linux/spinlock.h | 32 ++++++ include/linux/srcu.h | 5 + scripts/checkpatch.pl | 2 +- 17 files changed, 321 insertions(+), 7 deletions(-) create mode 100644 include/linux/cleanup.h
drivers/dma/ioat/dma.c +6 -6
@@ -584,11 +584,11 @@ desc_get_errstat(struct ioatdma_chan *ioat_chan, struct ioat_ring_ent *desc) }/** -* __cleanup - reclaim used descriptors +* __ioat_cleanup - reclaim used descriptors * @ioat_chan: channel (ring) to clean * @phys_complete: zeroed (or not) completion address (from status) */ -static void __cleanup (struct ioatdma_chan *ioat_chan,dma_addr_t phys_complete) +static void __ioat_cleanup (struct ioatdma_chan *ioat_chan,dma_addr_t phys_complete) {struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma;struct ioat_ring_ent *desc;
@@ -675,7 +675,7 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan)spin_lock_bh (&ioat_chan->cleanup_lock);if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete);if (is_ioat_halted (*ioat_chan->completion)) {u32 chanerr =readl (ioat_chan->reg_base +IOAT_CHANERR_OFFSET );
@@ -712,7 +712,7 @@ static void ioat_restart_channel(struct ioatdma_chan *ioat_chan)ioat_quiesce (ioat_chan,0 );if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete);__ioat_restart_chan (ioat_chan); }
@@ -786,7 +786,7 @@ static void ioat_eh(struct ioatdma_chan *ioat_chan)/* cleanup so tail points to descriptor that caused the error */ if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete); chanerr =readl (ioat_chan->reg_base +IOAT_CHANERR_OFFSET );pci_read_config_dword (pdev,IOAT_PCI_CHANERR_INT_OFFSET , &chanerr_int);
@@ -943,7 +943,7 @@ void ioat_timer_event(struct timer_list *t)/* timer restarted in ioat_cleanup_preamble * and IOAT_COMPLETION_ACK cleared */ -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete); goto unlock_out; }
include/linux/cleanup.h new file +171 -0
171 lines not on this page · raw message
include/linux/compiler-clang.h +9 -0
@@ -5,6 +5,15 @@/* Compiler specific definitions for Clang compiler */ +/* +* Clang prior to 17 is being silly and considers many __cleanup() variables +* as unused (because they are, their sole purpose is to go out of scope). +* +* https://reviews.llvm.org/D152180 +*/ +#undef __cleanup +#define __cleanup (func) __maybe_unused __attribute__((__cleanup__(func))) +/* same as gcc, this was present in clang-2.6 so we can assume it works * with any version that can compile the kernel */
include/linux/compiler_attributes.h +6 -0
@@ -80,6 +80,12 @@*/ #define __cold __attribute__((__cold__)) +/* +* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute +* clang: https://clang.llvm.org/docs/AttributeReference.html#cleanup +*/ +#define __cleanup (func) __attribute__((__cleanup__(func))) +/* * Note the long name. *
include/linux/device.h +7 -0
@@ -30,6 +30,7 @@#include <linux/device/bus.h> #include <linux/device/class.h> #include <linux/device/driver.h> +#include <linux/cleanup.h> #include <asm/device.h> struct device ;
@@ -822,6 +823,9 @@ void device_unregister(struct device *dev);void device_initialize (struct device *dev);int __must_check device_add (struct device *dev);void device_del (struct device *dev); + +DEFINE_FREE(device_del, struct device *, if (_T) device_del(_T)) +int device_for_each_child (struct device *dev,void *data,int (*fn)(struct device *dev,void *data)); int device_for_each_child_reverse(struct device *dev, void *data,
@@ -952,6 +956,9 @@ extern int (*platform_notify_remove)(struct device *dev);*/ struct device *get_device (struct device *dev);void put_device (struct device *dev); + +DEFINE_FREE(put_device, struct device *, if (_T) put_device(_T)) +bool kill_device (struct device *dev);#ifdef CONFIG_DEVTMPFS
include/linux/file.h +6 -0
@@ -10,6 +10,7 @@#include <linux/types.h> #include <linux/posix_types.h> #include <linux/errno.h> +#include <linux/cleanup.h> struct file ;
@@ -82,6 +83,8 @@ static inline void fdput_pos(struct fd f)fdput (f); } +DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd) +extern int f_dupfd (unsigned int from,struct file *file,unsigned flags);extern int replace_fd (unsigned fd,struct file *file,unsigned flags);extern void set_close_on_exec (unsigned int fd,int flag);
@@ -90,6 +93,9 @@ extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);extern int get_unused_fd_flags (unsigned flags);extern void put_unused_fd (unsigned int fd); +DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T), + get_unused_fd_flags(flags), unsigned flags) +extern void fd_install (unsigned int fd,struct file *file); extern int __receive_fd(struct file *file, int __user *ufd,
include/linux/irqflags.h +7 -0
@@ -13,6 +13,7 @@#define _LINUX_TRACE_IRQFLAGS_H#include <linux/typecheck.h> +#include <linux/cleanup.h> #include <asm/irqflags.h> #include <asm/percpu.h>
@@ -260,4 +261,10 @@ extern void warn_bogus_irq_restore(void);#define irqs_disabled_flags (flags) raw_irqs_disabled_flags(flags) +DEFINE_LOCK_GUARD_0(irq, local_irq_disable(), local_irq_enable()) +DEFINE_LOCK_GUARD_0 (irqsave, +local_irq_save (_T->flags), +local_irq_restore (_T->flags), + unsigned long flags) +#endif
include/linux/mutex.h +4 -0
@@ -19,6 +19,7 @@#include <asm/processor.h> #include <linux/osq_lock.h> #include <linux/debug_locks.h> +#include <linux/cleanup.h> struct device ;
@@ -246,4 +247,7 @@ extern void mutex_unlock(struct mutex *lock);extern int atomic_dec_and_mutex_lock (atomic_t *cnt,struct mutex *lock); +DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T)) +DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T)) +#endif /* __LINUX_MUTEX_H */
include/linux/percpu.h +4 -0
@@ -9,6 +9,7 @@#include <linux/printk.h> #include <linux/pfn.h> #include <linux/init.h> +#include <linux/cleanup.h> #include <asm/percpu.h>
@@ -134,6 +135,9 @@ extern void __init setup_per_cpu_areas(void);extern void __percpu *__alloc_percpu_gfp (size_t size,size_t align,gfp_t gfp);extern void __percpu *__alloc_percpu (size_t size,size_t align);extern void free_percpu (void __percpu *__pdata); + +DEFINE_FREE(free_percpu, void __percpu *, free_percpu(_T)) +extern phys_addr_t per_cpu_ptr_to_phys (void *addr);#define alloc_percpu_gfp (type, gfp) \
include/linux/preempt.h +47 -0
57 lines not on this page · raw message
include/linux/rcupdate.h +3 -0
@@ -27,6 +27,7 @@#include <linux/preempt.h> #include <linux/bottom_half.h> #include <linux/lockdep.h> +#include <linux/cleanup.h> #include <asm/processor.h> #include <linux/cpumask.h>
@@ -1060,4 +1061,6 @@ rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f)extern int rcu_expedited;extern int rcu_normal; +DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock()) +#endif /* __LINUX_RCUPDATE_H */
include/linux/rwsem.h +8 -0
@@ -16,6 +16,7 @@#include <linux/spinlock.h> #include <linux/atomic.h> #include <linux/err.h> +#include <linux/cleanup.h> #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __RWSEM_DEP_MAP_INIT (lockname) \
@@ -202,6 +203,13 @@ extern void up_read(struct rw_semaphore *sem);*/ extern void up_write (struct rw_semaphore *sem); +DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T)) +DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T)) + +DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T)) +DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T)) + +/* * downgrade write lock to read lock */
include/linux/sched/task.h +2 -0
@@ -142,6 +142,8 @@ static inline void put_task_struct(struct task_struct *t)__put_task_struct (t); } +DEFINE_FREE(put_task, struct task_struct *, if (_T) put_task_struct(_T)) +static inline void put_task_struct_many (struct task_struct *t,int nr) {if (refcount_sub_and_test (nr, &t->usage))
include/linux/slab.h +3 -0
@@ -17,6 +17,7 @@#include <linux/types.h> #include <linux/workqueue.h> #include <linux/percpu-refcount.h> +#include <linux/cleanup.h> /*
@@ -186,6 +187,8 @@ void kfree(const void *objp);void kfree_sensitive (const void *objp);size_t __ksize (const void *objp); +DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) +/** * ksize - Report actual allocation size of associated object *
include/linux/spinlock.h +32 -0
@@ -61,6 +61,7 @@#include <linux/stringify.h> #include <linux/bottom_half.h> #include <linux/lockdep.h> +#include <linux/cleanup.h> #include <asm/barrier.h> #include <asm/mmiowb.h>
@@ -506,4 +507,35 @@ int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,void free_bucket_spinlocks (spinlock_t *locks); +DEFINE_LOCK_GUARD_1 (raw_spinlock, raw_spinlock_t, +raw_spin_lock (_T->lock), + raw_spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_nested, raw_spinlock_t, +raw_spin_lock_nested (_T->lock,SINGLE_DEPTH_NESTING ), + raw_spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_irq, raw_spinlock_t, +raw_spin_lock_irq (_T->lock), + raw_spin_unlock_irq(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_irqsave, raw_spinlock_t, +raw_spin_lock_irqsave (_T->lock, _T->flags), +raw_spin_unlock_irqrestore (_T->lock, _T->flags), + unsigned long flags) + +DEFINE_LOCK_GUARD_1 (spinlock, spinlock_t, +spin_lock (_T->lock), + spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (spinlock_irq, spinlock_t, +spin_lock_irq (_T->lock), + spin_unlock_irq(_T->lock)) + +DEFINE_LOCK_GUARD_1 (spinlock_irqsave, spinlock_t, +spin_lock_irqsave (_T->lock, _T->flags), +spin_unlock_irqrestore (_T->lock, _T->flags), + unsigned long flags) + +#undef __LINUX_INSIDE_SPINLOCK_H#endif /* __LINUX_SPINLOCK_H */
include/linux/srcu.h +5 -0
@@ -211,4 +211,9 @@ static inline void smp_mb__after_srcu_read_unlock(void)/* __srcu_read_unlock has smp_mb() internally so nothing to do here. */ } +DEFINE_LOCK_GUARD_1(srcu, struct srcu_struct, + _T->idx = srcu_read_lock(_T->lock), + srcu_read_unlock(_T->lock, _T->idx), + int idx) +#endif
scripts/checkpatch.pl +1 -1
@@ -4895,7 +4895,7 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__|scoped_guard)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/2 fscontext: do not consume log entries when returning -EMSGSIZE
From: Aleksa Sarai <[email protected]>
[ Upstream commit 72d271a7baa7062cb27e774ac37c5459c6d20e22 ]
Userspace generally expects APIs that return -EMSGSIZE to allow for them to adjust their buffer size and retry the operation. However, the fscontext log would previously clear the message even in the -EMSGSIZE case.
Given that it is very cheap for us to check whether the buffer is too small before we remove the message from the ring buffer, let's just do that instead. While we're at it, refactor some fscontext_read() into a separate helper to make the ring buffer logic a bit easier to read.
--- fs/fsopen.c | 70 +++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 32 deletions(-)
fs/fsopen.c +38 -32
@@ -18,50 +18,56 @@#include "internal.h" #include "mount.h" +static inline const char *fetch_message_locked (struct fc_log *log,size_t len, +bool *need_free) +{ +const char *p; +int index; + +if (unlikely (log->head == log->tail)) +return ERR_PTR (-ENODATA ); + + index = log->tail & (ARRAY_SIZE (log->buffer) -1 ); + p = log->buffer[index]; +if (unlikely (strlen (p) > len)) +return ERR_PTR (-EMSGSIZE ); + + log->buffer[index] =NULL ; + *need_free = log->need_free & (1 << index); + log->need_free &= ~(1 << index); + log->tail++; + +return p; +} +/* * Allow the user to read back any error, warning or informational messages. +* Only one message is returned for each read(2) call. */ static ssize_t fscontext_read (struct file *file,char __user *_buf,size_t len,loff_t *pos) {struct fs_context *fc = file->private_data; -struct fc_log *log = fc->log.log; -unsigned int logsize =ARRAY_SIZE (log->buffer); -ssize_t ret; -char *p; +ssize_t err; + const char *p __free(kfree) = NULL, *message;bool need_free; -int index, n; +int n; - ret =mutex_lock_interruptible (&fc->uapi_mutex); -if (ret <0 ) -return ret; - -if (log->head == log->tail) { -mutex_unlock (&fc->uapi_mutex); -return -ENODATA ; - } - - index = log->tail & (logsize -1 ); - p = log->buffer[index]; - need_free = log->need_free & (1 << index); - log->buffer[index] =NULL ; - log->need_free &= ~(1 << index); - log->tail++; + err =mutex_lock_interruptible (&fc->uapi_mutex); +if (err <0 ) +return err; + message =fetch_message_locked (fc->log.log, len, &need_free);mutex_unlock (&fc->uapi_mutex); +if (IS_ERR (message)) +return PTR_ERR (message); - ret = -EMSGSIZE ; - n =strlen (p); -if (n > len) - goto err_free; - ret = -EFAULT ; -if (copy_to_user (_buf, p, n) !=0 ) - goto err_free; - ret = n; - -err_free:if (need_free) -kfree (p); -return ret; + p = message; + + n =strlen (message); +if (copy_to_user (_buf, message, n)) +return -EFAULT ; +return n; }static int fscontext_release (struct inode *inode,struct file *file)
Signature · 1 line
2.51.0