On 1/4/26 22:17, Mikulas Patocka wrote:
> If a process sets up a timer that periodically sends a signal in short
> intervals and if it executes some kernel code that calls
> mm_take_all_locks, we get random -EINTR failures.
> 
> The function mm_take_all_locks fails with -EINTR if there is pending
> signal. The -EINTR is propagated up the call stack to userspace and
> userspace fails if it gets this error.

That is perfectly expected behavior.

> In order to fix these failures, this commit changes
> signal_pending(current) to fatal_signal_pending(current) in
> mm_take_all_locks, so that it is interrupted only if the signal is
> actually killing the process.
> 
> For example, this bug happens when using OpenCL on AMDGPU. Sometimes,
> probing the OpenCL device fails (strace shows that open("/dev/kfd")
> failed with -EINTR). Sometimes we get the message "amdgpu:
> init_user_pages: Failed to register MMU notifier: -4" in the syslog.

Yeah, that's because the ROCm userspace components doesn't work well with 
signals (and that is documented) but that is not the fault of the kernel.

Could be that the kernel driver prints some incorrect error messages, but 
that's about it.

So as far as I can see you try to work around problems in ROCm userspace 
libraries. Please don't do that!

If you find an issue like this the correct approach is to fix ROCm libraries 
instead, most likely the thunk component.

Regards,
Christian.

> 
> The bug can be reproduced with the following program.
> 
> To run this program, you need AMD graphics card and the package
> "rocm-opencl" installed. You must not have the package "mesa-opencl-icd"
> installed, because it redirects the default OpenCL implementation to
> itself.
> 
> include <stdio.h>
> include <stdlib.h>
> include <unistd.h>
> include <string.h>
> include <signal.h>
> include <sys/time.h>
> 
> define CL_TARGET_OPENCL_VERSION       300
> include <CL/opencl.h>
> 
> static void fn(void)
> {
>       while (1) {
>               int32_t err;
>               cl_device_id device;
>               err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device, 
> NULL);
>               if (err != CL_SUCCESS) {
>                       fprintf(stderr, "clGetDeviceIDs failed: %d\n", err);
>                       exit(1);
>               }
>               write(2, "-", 1);
>       }
> }
> 
> static void alrm(int sig)
> {
>       write(2, ".", 1);
> }
> 
> int main(void)
> {
>       struct itimerval it;
>       struct sigaction sa;
>       memset(&sa, 0, sizeof sa);
>       sa.sa_handler = alrm;
>       sa.sa_flags = SA_RESTART;
>       sigaction(SIGALRM, &sa, NULL);
>       it.it_interval.tv_sec = 0;
>       it.it_interval.tv_usec = 50;
>       it.it_value.tv_sec = 0;
>       it.it_value.tv_usec = 50;
>       setitimer(ITIMER_REAL, &it, NULL);
>       fn();
>       return 1;
> }
> 
> I'm submitting this patch for the stable kernels, because this bug may
> cause random failures in any code that calls mm_take_all_locks.
> 
> Signed-off-by: Mikulas Patocka <[email protected]>
> Link: https://lists.freedesktop.org/archives/amd-gfx/2025-November/133141.html
> Link: 
> https://yhbt.net/lore/linux-mm/[email protected]/T/#u
> Cc: [email protected]
> Fixes: 7906d00cd1f6 ("mmu-notifiers: add mm_take_all_locks() operation")
> 
> ---
>  mm/vma.c |    8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> Index: mm/mm/vma.c
> ===================================================================
> --- mm.orig/mm/vma.c  2026-01-04 21:19:13.000000000 +0100
> +++ mm/mm/vma.c       2026-01-04 21:19:13.000000000 +0100
> @@ -2166,14 +2166,14 @@ int mm_take_all_locks(struct mm_struct *
>        * is reached.
>        */
>       for_each_vma(vmi, vma) {
> -             if (signal_pending(current))
> +             if (fatal_signal_pending(current))
>                       goto out_unlock;
>               vma_start_write(vma);
>       }
>  
>       vma_iter_init(&vmi, mm, 0);
>       for_each_vma(vmi, vma) {
> -             if (signal_pending(current))
> +             if (fatal_signal_pending(current))
>                       goto out_unlock;
>               if (vma->vm_file && vma->vm_file->f_mapping &&
>                               is_vm_hugetlb_page(vma))
> @@ -2182,7 +2182,7 @@ int mm_take_all_locks(struct mm_struct *
>  
>       vma_iter_init(&vmi, mm, 0);
>       for_each_vma(vmi, vma) {
> -             if (signal_pending(current))
> +             if (fatal_signal_pending(current))
>                       goto out_unlock;
>               if (vma->vm_file && vma->vm_file->f_mapping &&
>                               !is_vm_hugetlb_page(vma))
> @@ -2191,7 +2191,7 @@ int mm_take_all_locks(struct mm_struct *
>  
>       vma_iter_init(&vmi, mm, 0);
>       for_each_vma(vmi, vma) {
> -             if (signal_pending(current))
> +             if (fatal_signal_pending(current))
>                       goto out_unlock;
>               if (vma->anon_vma)
>                       list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
> 

Reply via email to