浏览代码

NFSv4: Ensure the callback daemon flushes signals

If the callback daemon is signalled, but is unable to exit because it still
has users, then we need to flush signals. If not, then svc_recv() can
never sleep, and so we hang.
If we flush signals, then we also have to be prepared to resend them when
we want the thread to exit.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Trond Myklebust 19 年之前
父节点
当前提交
1dd761e907
共有 1 个文件被更改,包括 13 次插入6 次删除
  1. 13 6
      fs/nfs/callback.c

+ 13 - 6
fs/nfs/callback.c

@@ -55,7 +55,12 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
 
 
 	complete(&nfs_callback_info.started);
 	complete(&nfs_callback_info.started);
 
 
-	while (nfs_callback_info.users != 0 || !signalled()) {
+	for(;;) {
+		if (signalled()) {
+			if (nfs_callback_info.users == 0)
+				break;
+			flush_signals(current);
+		}
 		/*
 		/*
 		 * Listen for a request on the socket
 		 * Listen for a request on the socket
 		 */
 		 */
@@ -135,11 +140,13 @@ int nfs_callback_down(void)
 
 
 	lock_kernel();
 	lock_kernel();
 	down(&nfs_callback_sema);
 	down(&nfs_callback_sema);
-	if (--nfs_callback_info.users || nfs_callback_info.pid == 0)
-		goto out;
-	kill_proc(nfs_callback_info.pid, SIGKILL, 1);
-	wait_for_completion(&nfs_callback_info.stopped);
-out:
+	nfs_callback_info.users--;
+	do {
+		if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0)
+			break;
+		if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0)
+			break;
+	} while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0);
 	up(&nfs_callback_sema);
 	up(&nfs_callback_sema);
 	unlock_kernel();
 	unlock_kernel();
 	return ret;
 	return ret;