diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
| -rw-r--r-- | net/sunrpc/clnt.c | 71 |
1 files changed, 37 insertions, 34 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index c979fcf88798..f17e6153b688 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -378,38 +378,41 @@ rpc_default_callback(struct rpc_task *task) | |||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | /* | 380 | /* |
| 381 | * Export the signal mask handling for aysnchronous code that | 381 | * Export the signal mask handling for synchronous code that |
| 382 | * sleeps on RPC calls | 382 | * sleeps on RPC calls |
| 383 | */ | 383 | */ |
| 384 | #define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL)) | ||
| 384 | 385 | ||
| 386 | static void rpc_save_sigmask(sigset_t *oldset, int intr) | ||
| 387 | { | ||
| 388 | unsigned long sigallow = 0; | ||
| 389 | sigset_t sigmask; | ||
| 390 | |||
| 391 | /* Block all signals except those listed in sigallow */ | ||
| 392 | if (intr) | ||
| 393 | sigallow |= RPC_INTR_SIGNALS; | ||
| 394 | siginitsetinv(&sigmask, sigallow); | ||
| 395 | sigprocmask(SIG_BLOCK, &sigmask, oldset); | ||
| 396 | } | ||
| 397 | |||
| 398 | static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset) | ||
| 399 | { | ||
| 400 | rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task)); | ||
| 401 | } | ||
| 402 | |||
| 403 | static inline void rpc_restore_sigmask(sigset_t *oldset) | ||
| 404 | { | ||
| 405 | sigprocmask(SIG_SETMASK, oldset, NULL); | ||
| 406 | } | ||
| 407 | |||
| 385 | void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset) | 408 | void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset) |
| 386 | { | 409 | { |
| 387 | unsigned long sigallow = sigmask(SIGKILL); | 410 | rpc_save_sigmask(oldset, clnt->cl_intr); |
| 388 | unsigned long irqflags; | ||
| 389 | |||
| 390 | /* Turn off various signals */ | ||
| 391 | if (clnt->cl_intr) { | ||
| 392 | struct k_sigaction *action = current->sighand->action; | ||
| 393 | if (action[SIGINT-1].sa.sa_handler == SIG_DFL) | ||
| 394 | sigallow |= sigmask(SIGINT); | ||
| 395 | if (action[SIGQUIT-1].sa.sa_handler == SIG_DFL) | ||
| 396 | sigallow |= sigmask(SIGQUIT); | ||
| 397 | } | ||
| 398 | spin_lock_irqsave(¤t->sighand->siglock, irqflags); | ||
| 399 | *oldset = current->blocked; | ||
| 400 | siginitsetinv(¤t->blocked, sigallow & ~oldset->sig[0]); | ||
| 401 | recalc_sigpending(); | ||
| 402 | spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); | ||
| 403 | } | 411 | } |
| 404 | 412 | ||
| 405 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) | 413 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) |
| 406 | { | 414 | { |
| 407 | unsigned long irqflags; | 415 | rpc_restore_sigmask(oldset); |
| 408 | |||
| 409 | spin_lock_irqsave(¤t->sighand->siglock, irqflags); | ||
| 410 | current->blocked = *oldset; | ||
| 411 | recalc_sigpending(); | ||
| 412 | spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); | ||
| 413 | } | 416 | } |
| 414 | 417 | ||
| 415 | /* | 418 | /* |
| @@ -427,26 +430,26 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
| 427 | 430 | ||
| 428 | BUG_ON(flags & RPC_TASK_ASYNC); | 431 | BUG_ON(flags & RPC_TASK_ASYNC); |
| 429 | 432 | ||
| 430 | rpc_clnt_sigmask(clnt, &oldset); | ||
| 431 | |||
| 432 | status = -ENOMEM; | 433 | status = -ENOMEM; |
| 433 | task = rpc_new_task(clnt, NULL, flags); | 434 | task = rpc_new_task(clnt, NULL, flags); |
| 434 | if (task == NULL) | 435 | if (task == NULL) |
| 435 | goto out; | 436 | goto out; |
| 436 | 437 | ||
| 438 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ | ||
| 439 | rpc_task_sigmask(task, &oldset); | ||
| 440 | |||
| 437 | rpc_call_setup(task, msg, 0); | 441 | rpc_call_setup(task, msg, 0); |
| 438 | 442 | ||
| 439 | /* Set up the call info struct and execute the task */ | 443 | /* Set up the call info struct and execute the task */ |
| 440 | if (task->tk_status == 0) | 444 | if (task->tk_status == 0) { |
| 441 | status = rpc_execute(task); | 445 | status = rpc_execute(task); |
| 442 | else { | 446 | } else { |
| 443 | status = task->tk_status; | 447 | status = task->tk_status; |
| 444 | rpc_release_task(task); | 448 | rpc_release_task(task); |
| 445 | } | 449 | } |
| 446 | 450 | ||
| 451 | rpc_restore_sigmask(&oldset); | ||
| 447 | out: | 452 | out: |
| 448 | rpc_clnt_sigunmask(clnt, &oldset); | ||
| 449 | |||
| 450 | return status; | 453 | return status; |
| 451 | } | 454 | } |
| 452 | 455 | ||
| @@ -467,8 +470,6 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
| 467 | 470 | ||
| 468 | flags |= RPC_TASK_ASYNC; | 471 | flags |= RPC_TASK_ASYNC; |
| 469 | 472 | ||
| 470 | rpc_clnt_sigmask(clnt, &oldset); | ||
| 471 | |||
| 472 | /* Create/initialize a new RPC task */ | 473 | /* Create/initialize a new RPC task */ |
| 473 | if (!callback) | 474 | if (!callback) |
| 474 | callback = rpc_default_callback; | 475 | callback = rpc_default_callback; |
| @@ -477,6 +478,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
| 477 | goto out; | 478 | goto out; |
| 478 | task->tk_calldata = data; | 479 | task->tk_calldata = data; |
| 479 | 480 | ||
| 481 | /* Mask signals on GSS_AUTH upcalls */ | ||
| 482 | rpc_task_sigmask(task, &oldset); | ||
| 483 | |||
| 480 | rpc_call_setup(task, msg, 0); | 484 | rpc_call_setup(task, msg, 0); |
| 481 | 485 | ||
| 482 | /* Set up the call info struct and execute the task */ | 486 | /* Set up the call info struct and execute the task */ |
| @@ -486,9 +490,8 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
| 486 | else | 490 | else |
| 487 | rpc_release_task(task); | 491 | rpc_release_task(task); |
| 488 | 492 | ||
| 493 | rpc_restore_sigmask(&oldset); | ||
| 489 | out: | 494 | out: |
| 490 | rpc_clnt_sigunmask(clnt, &oldset); | ||
| 491 | |||
| 492 | return status; | 495 | return status; |
| 493 | } | 496 | } |
| 494 | 497 | ||
| @@ -666,7 +669,7 @@ call_allocate(struct rpc_task *task) | |||
| 666 | return; | 669 | return; |
| 667 | printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); | 670 | printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); |
| 668 | 671 | ||
| 669 | if (RPC_IS_ASYNC(task) || !(task->tk_client->cl_intr && signalled())) { | 672 | if (RPC_IS_ASYNC(task) || !signalled()) { |
| 670 | xprt_release(task); | 673 | xprt_release(task); |
| 671 | task->tk_action = call_reserve; | 674 | task->tk_action = call_reserve; |
| 672 | rpc_delay(task, HZ>>4); | 675 | rpc_delay(task, HZ>>4); |
