Commit 8d3ca331 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Don't allow waiting for exiting tasks



Once a task calls exit_signals() it can no longer be signalled. So do
not allow it to do killable waits.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 14e41b16
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)

int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
{
	if (unlikely(nfs_current_task_exiting()))
		return -EINTR;
	schedule();
	if (signal_pending_state(mode, current))
		return -ERESTARTSYS;
+5 −0
Original line number Diff line number Diff line
@@ -912,6 +912,11 @@ static inline u32 nfs_stateid_hash(nfs4_stateid *stateid)
}
#endif

static inline bool nfs_current_task_exiting(void)
{
	return (current->flags & PF_EXITING) != 0;
}

static inline bool nfs_error_is_fatal(int err)
{
	switch (err) {
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
		__set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
		schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
		res = -ERESTARTSYS;
	} while (!fatal_signal_pending(current));
	} while (!fatal_signal_pending(current) && !nfs_current_task_exiting());
	return res;
}

+7 −2
Original line number Diff line number Diff line
@@ -446,6 +446,8 @@ static int nfs4_delay_killable(long *timeout)
{
	might_sleep();

	if (unlikely(nfs_current_task_exiting()))
		return -EINTR;
	__set_current_state(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE);
	schedule_timeout(nfs4_update_delay(timeout));
	if (!__fatal_signal_pending(current))
@@ -457,6 +459,8 @@ static int nfs4_delay_interruptible(long *timeout)
{
	might_sleep();

	if (unlikely(nfs_current_task_exiting()))
		return -EINTR;
	__set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE_UNSAFE);
	schedule_timeout(nfs4_update_delay(timeout));
	if (!signal_pending(current))
@@ -1777,7 +1781,8 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
		rcu_read_unlock();
		trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);

		if (!fatal_signal_pending(current)) {
		if (!fatal_signal_pending(current) &&
		    !nfs_current_task_exiting()) {
			if (schedule_timeout(5*HZ) == 0)
				status = -EAGAIN;
			else
@@ -3581,7 +3586,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
		write_sequnlock(&state->seqlock);
		trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);

		if (fatal_signal_pending(current))
		if (fatal_signal_pending(current) || nfs_current_task_exiting())
			status = -EINTR;
		else
			if (schedule_timeout(5*HZ) != 0)