Skip to content

Commit 9b80856

Browse files
pcd1193182Ryan Moeller
authored andcommitted
Add SIGSTOP and SIGTSTP handling to issig
This change adds SIGSTOP and SIGTSTP handling to the issig function; this mirrors its behavior on Solaris. This way, long running kernel tasks can be stopped with the appropriate signals. Note that doing so with ctrl-z on the command line doesn't return control of the tty to the shell, because tty handling is done separately from stopping the process. That can be future work, if people feel that it is a necessary addition. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matthew Ahrens <[email protected]> Signed-off-by: Paul Dagnelie <[email protected]> Issue openzfs#810 Issue openzfs#10843 Closes openzfs#11801
1 parent d9374e5 commit 9b80856

File tree

7 files changed

+134
-17
lines changed

7 files changed

+134
-17
lines changed

config/kernel-siginfo.m4

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
dnl #
2+
dnl # 4.20 API change
3+
dnl # Added kernel_siginfo_t
4+
dnl #
5+
AC_DEFUN([ZFS_AC_KERNEL_SRC_SIGINFO], [
6+
ZFS_LINUX_TEST_SRC([siginfo], [
7+
#include <linux/signal_types.h>
8+
],[
9+
kernel_siginfo_t info __attribute__ ((unused));
10+
])
11+
])
12+
13+
AC_DEFUN([ZFS_AC_KERNEL_SIGINFO], [
14+
AC_MSG_CHECKING([whether kernel_siginfo_t tyepedef exists])
15+
ZFS_LINUX_TEST_RESULT([siginfo], [
16+
AC_MSG_RESULT(yes)
17+
AC_DEFINE(HAVE_SIGINFO, 1, [kernel_siginfo_t exists])
18+
],[
19+
AC_MSG_RESULT(no)
20+
])
21+
])

config/kernel-signal-stop.m4

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
dnl #
2+
dnl # 4.4 API change
3+
dnl # Added kernel_signal_stop
4+
dnl #
5+
AC_DEFUN([ZFS_AC_KERNEL_SRC_SIGNAL_STOP], [
6+
ZFS_LINUX_TEST_SRC([signal_stop], [
7+
#include <linux/sched/signal.h>
8+
],[
9+
kernel_signal_stop();
10+
])
11+
])
12+
13+
AC_DEFUN([ZFS_AC_KERNEL_SIGNAL_STOP], [
14+
AC_MSG_CHECKING([whether signal_stop() exists])
15+
ZFS_LINUX_TEST_RESULT([signal_stop], [
16+
AC_MSG_RESULT(yes)
17+
AC_DEFINE(HAVE_SIGNAL_STOP, 1, [signal_stop() exists])
18+
],[
19+
AC_MSG_RESULT(no)
20+
])
21+
])

config/kernel-special-state.m4

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
dnl #
2+
dnl # 4.17 API change
3+
dnl # Added set_special_state() function
4+
dnl #
5+
AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE], [
6+
ZFS_LINUX_TEST_SRC([set_special_state], [
7+
#include <linux/sched.h>
8+
],[
9+
set_special_state(TASK_STOPPED);
10+
])
11+
])
12+
13+
AC_DEFUN([ZFS_AC_KERNEL_SET_SPECIAL_STATE], [
14+
AC_MSG_CHECKING([whether set_special_state() exists])
15+
ZFS_LINUX_TEST_RESULT([set_special_state], [
16+
AC_MSG_RESULT(yes)
17+
AC_DEFINE(HAVE_SET_SPECIAL_STATE, 1, [set_special_state() exists])
18+
],[
19+
AC_MSG_RESULT(no)
20+
])
21+
])

config/kernel.m4

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
128128
ZFS_AC_KERNEL_SRC_MKNOD
129129
ZFS_AC_KERNEL_SRC_SYMLINK
130130
ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
131+
ZFS_AC_KERNEL_SRC_SIGNAL_STOP
132+
ZFS_AC_KERNEL_SRC_SIGINFO
133+
ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE
131134
132135
AC_MSG_CHECKING([for available kernel interfaces])
133136
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
@@ -229,6 +232,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
229232
ZFS_AC_KERNEL_MKNOD
230233
ZFS_AC_KERNEL_SYMLINK
231234
ZFS_AC_KERNEL_BIO_MAX_SEGS
235+
ZFS_AC_KERNEL_SIGNAL_STOP
236+
ZFS_AC_KERNEL_SIGINFO
237+
ZFS_AC_KERNEL_SET_SPECIAL_STATE
232238
])
233239

234240
dnl #

include/os/linux/spl/sys/signal.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,6 @@
3333
#define FORREAL 0 /* Usual side-effects */
3434
#define JUSTLOOKING 1 /* Don't stop the process */
3535

36-
/*
37-
* The "why" argument indicates the allowable side-effects of the call:
38-
*
39-
* FORREAL: Extract the next pending signal from p_sig into p_cursig;
40-
* stop the process if a stop has been requested or if a traced signal
41-
* is pending.
42-
*
43-
* JUSTLOOKING: Don't stop the process, just indicate whether or not
44-
* a signal might be pending (FORREAL is needed to tell for sure).
45-
*/
46-
static __inline__ int
47-
issig(int why)
48-
{
49-
ASSERT(why == FORREAL || why == JUSTLOOKING);
50-
51-
return (signal_pending(current));
52-
}
36+
extern int issig(int why);
5337

5438
#endif /* SPL_SIGNAL_H */

include/os/linux/spl/sys/thread.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,17 @@ extern struct task_struct *spl_kthread_create(int (*func)(void *),
7070

7171
extern proc_t p0;
7272

73+
#ifdef HAVE_SIGINFO
74+
typedef kernel_siginfo_t spl_kernel_siginfo_t;
75+
#else
76+
typedef siginfo_t spl_kernel_siginfo_t;
77+
#endif
78+
79+
#ifdef HAVE_SET_SPECIAL_STATE
80+
#define spl_set_special_state(x) set_special_state((x))
81+
#else
82+
#define spl_set_special_state(x) __set_current_state((x))
83+
#endif
84+
85+
7386
#endif /* _SPL_THREAD_H */

module/os/linux/spl/spl-thread.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,54 @@ spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...)
158158
} while (1);
159159
}
160160
EXPORT_SYMBOL(spl_kthread_create);
161+
162+
/*
163+
* The "why" argument indicates the allowable side-effects of the call:
164+
*
165+
* FORREAL: Extract the next pending signal from p_sig into p_cursig;
166+
* stop the process if a stop has been requested or if a traced signal
167+
* is pending.
168+
*
169+
* JUSTLOOKING: Don't stop the process, just indicate whether or not
170+
* a signal might be pending (FORREAL is needed to tell for sure).
171+
*/
172+
int
173+
issig(int why)
174+
{
175+
ASSERT(why == FORREAL || why == JUSTLOOKING);
176+
177+
if (!signal_pending(current))
178+
return (0);
179+
180+
if (why != FORREAL)
181+
return (1);
182+
183+
struct task_struct *task = current;
184+
spl_kernel_siginfo_t __info;
185+
sigset_t set;
186+
siginitsetinv(&set, 1ULL << (SIGSTOP - 1) | 1ULL << (SIGTSTP - 1));
187+
sigorsets(&set, &task->blocked, &set);
188+
189+
spin_lock_irq(&task->sighand->siglock);
190+
int ret;
191+
if ((ret = dequeue_signal(task, &set, &__info)) != 0) {
192+
#ifdef HAVE_SIGNAL_STOP
193+
spin_unlock_irq(&task->sighand->siglock);
194+
kernel_signal_stop();
195+
#else
196+
if (current->jobctl & JOBCTL_STOP_DEQUEUED)
197+
spl_set_special_state(TASK_STOPPED);
198+
199+
spin_unlock_irq(&current->sighand->siglock);
200+
201+
schedule();
202+
#endif
203+
return (0);
204+
}
205+
206+
spin_unlock_irq(&task->sighand->siglock);
207+
208+
return (1);
209+
}
210+
211+
EXPORT_SYMBOL(issig);

0 commit comments

Comments
 (0)