Fix failures with signals and AMD OpenCL
Subsystems (6)
v4 cover Fix failures with signals and AMD OpenCL
This patch set fixes failures with AMD OpenCL and signals.
The first patch makes the kernel return -ERESTARTSYS instead of -EINTR, so that the syscall is restarted if the signal has the SA_RESTART flag.
The second patch removes a spurious error message.
Mikulas
PATCH v4 1/2 mm_take_all_locks: change -EINTR to -ERESTARTSYS
If a process receives a signal while it executes some kernel code that calls mm_take_all_locks, we get -EINTR error. The -EINTR is propagated up the call stack to userspace and userspace may fail if it gets this error.
This commit changes -EINTR to -ERESTARTSYS, so that if the signal handler was installed with the SA_RESTART flag, the operation is automatically restarted.
For example, this problem happens when using OpenCL on AMDGPU. If some signal races with clGetDeviceIDs, clGetDeviceIDs returns an error CL_DEVICE_NOT_FOUND (and strace shows that open("/dev/kfd") failed with EINTR).
This problem 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 the AMD ROCm stack fails if it receives EINTR from open (it seems to restart EINTR from ioctl correctly). The process may receive signals at unpredictable times, so the OpenCL implementation may fail at unpredictable times.
--- mm/vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vma.c +1 -1
@@ -2202,7 +2202,7 @@ int mm_take_all_locks(struct mm_struct * out_unlock:mm_drop_all_locks (mm); -return -EINTR ; +return -ERESTARTSYS ; }static void vm_unlock_anon_vma (struct anon_vma *anon_vma)
Re: [PATCH v4 1/2] mm_take_all_locks: change -EINTR to -ERESTARTSYS
Quoted 3 lines · Mikulas Patocka
This commit changes
-EINTRto-ERESTARTSYS, so that if the signal handler was installed with theSA_RESTARTflag, the operation is automatically restarted.
No, this is bonkers. If you get a signal, you return -EINTR.
Re: [PATCH v4 1/2] mm_take_all_locks: change -EINTR to -ERESTARTSYS
Quoted 6 lines · Matthew Wilcox
Quoted 3 lines · Mikulas Patocka
This commit changes
-EINTRto-ERESTARTSYS, so that if the signal handler was installed with theSA_RESTARTflag, the operation is automatically restarted.No, this is bonkers. If you get a signal, you return
-EINTR.
Why?
fifo_open returns -ERESTARTSYS, so why not here?
Mikulas
Re: [PATCH v4 1/2] mm_take_all_locks: change -EINTR to -ERESTARTSYS
Quoted 9 lines · Mikulas Patocka
Quoted 5 lines · Matthew Wilcox
Quoted 3 lines · Mikulas Patocka
This commit changes
-EINTRto-ERESTARTSYS, so that if the signal handler was installed with theSA_RESTARTflag, the operation is automatically restarted.
Quoted 5 lines
Quoted 1 line
No, this is bonkers. If you get a signal, you return
-EINTR.Why?
fifo_openreturns-ERESTARTSYS, so why not here?
This is fundamentally changing what this does for all callers, and we've simply not encountered this issue elsewhere.
Given how long it might take to work it might be interrupted by another signal on the next attempt, whose to say that it might not result in a situation where it can never complete?
I thnk it should stay as it is.
Also the comment above literally has:
* mm_take_all_locks() and mm_drop_all_locks are expensive operations
* that may have to take thousand of locks.
*
* mm_take_all_locks() can fail if it's interrupted by signals. */
Which at any rate would need to be changed even if we were to change it.
I'm more and more inclined to say let's just drop this series in general, and you should go fix how signals are handled in the driver/userland code.
This is really feeling like the wrong place to fix this.
Quoted 3 lines
Mikulas
Cheers, Lorenzo
Re: [PATCH v4 1/2] mm_take_all_locks: change -EINTR to -ERESTARTSYS
In reply to Mikulas PatockaQuoted 14 lines · Mikulas Patocka
If a process receives a signal while it executes some kernel code that calls
mm_take_all_locks, we get-EINTRerror. The-EINTRis propagated up the call stack to userspace and userspace may fail if it gets this error.This commit changes
-EINTRto-ERESTARTSYS, so that if the signal handler was installed with theSA_RESTARTflag, the operation is automatically restarted.For example, this problem happens when using OpenCL on AMDGPU. If some signal races with clGetDeviceIDs, clGetDeviceIDs returns an error
CL_DEVICE_NOT_FOUND(and strace shows thatopen("/dev/kfd")failed with EINTR).
Quoted 6 lines
This problem 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.
What about [1]? This reproducer should be fixed in the ROCm userspace library, as stated by Christian König.
1. https://lore.kernel.org/linux-mm/[email protected]/
Thanks,
Liam
PATCH v4 2/2 amdgpu: delete the "Failed to register MMU notifier" message
In reply to Mikulas PatockaThis error may happen if mm_take_all_locks was interrupted by a signal - the userspace will retry an ioctl that returned -EINTR, so there is no need to report it to the syslog.
Christian König suggested to remove this message at all, so let's do it.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +1 -4
@@ -1069,11 +1069,8 @@ static int init_user_pages(struct kgd_me } ret =amdgpu_hmm_register (bo, user_addr); -if (ret) { -pr_err ("%s: Failed to register MMU notifier: %d\n" , - __func__, ret); +if (ret) goto out; - }if (criu_resume) {/*
Re: [PATCH v4 2/2] amdgpu: delete the "Failed to register MMU notifier" message
Quoted 7 lines · Mikulas Patocka
This error may happen if
mm_take_all_lockswas interrupted by a signal - the userspace will retry an ioctl that returned-EINTR, so there is no need to report it to the syslog.Christian König suggested to remove this message at all, so let's do it.
Signed-off-by Mikulas Patocka <[email protected]>
I don't really see the point in this being part of the series here... seems to me a patch that could be applied any time, so why not send that separately to the amd driver people?
I mean maybe it's not al that important but still.
Quoted 24 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)Index:
mm/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
===================================================================drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +1
-4@@ -1069,11 +1069,8 @@ static int init_user_pages(struct kgd_me } ret =amdgpu_hmm_register (bo, user_addr); -if (ret) { -pr_err ("%s: Failed to register MMU notifier: %d\n" , - __func__, ret); +if (ret) goto out; - }if (criu_resume) {/*
Re: [PATCH v4 2/2] amdgpu: delete the "Failed to register MMU notifier" message
Quoted 7 lines · Lorenzo Stoakes
Quoted 6 lines · Mikulas Patocka
This error may happen if
mm_take_all_lockswas interrupted by a signal - the userspace will retry an ioctl that returned-EINTR, so there is no need to report it to the syslog.Christian König suggested to remove this message at all, so let's do it.
Quoted 7 lines
Quoted 1 line
Signed-off-by Mikulas Patocka <[email protected]>I don't really see the point in this being part of the series here... seems to me a patch that could be applied any time, so why not send that separately to the amd driver people?
I mean maybe it's not al that important but still.
I really think changing this to info would be better. It was (and may be) useful to some?
Obviously the amd folks need to work on signal handling and this would help them..
But then again, as Lorenzo said, we don't really need to be involved in this patch.
Quoted 25 lines
Quoted 25 lines
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)Index:
mm/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
===================================================================drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +1
-4@@ -1069,11 +1069,8 @@ static int init_user_pages(struct kgd_me } ret =amdgpu_hmm_register (bo, user_addr); -if (ret) { -pr_err ("%s: Failed to register MMU notifier: %d\n" , - __func__, ret); +if (ret) goto out; - }if (criu_resume) {/*