diff options
| author | David Howells <dhowells@redhat.com> | 2019-05-09 03:21:21 -0400 |
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2019-05-16 11:25:20 -0400 |
| commit | b960a34b73e4c1c972623bc2076e24b97588d09e (patch) | |
| tree | b7fafd6110ffa1aed594d55097755eea65da5d8d | |
| parent | 0ab4c9594812c4bc5606daf0677ae304bf7ec8c8 (diff) | |
rxrpc: Allow the kernel to mark a call as being non-interruptible
Allow kernel services using AF_RXRPC to indicate that a call should be
non-interruptible. This allows kafs to make things like lock-extension and
writeback data storage calls non-interruptible.
If this is set, signals will be ignored for operations on that call where
possible - such as waiting to get a call channel on an rxrpc connection.
It doesn't prevent UDP sendmsg from being interrupted, but that will be
handled by packet retransmission.
rxrpc_kernel_recv_data() isn't affected by this since that never waits,
preferring instead to return -EAGAIN and leave the waiting to the caller.
Userspace initiated calls can't be set to be uninterruptible at this time.
Signed-off-by: David Howells <dhowells@redhat.com>
| -rw-r--r-- | Documentation/networking/rxrpc.txt | 11 | ||||
| -rw-r--r-- | fs/afs/rxrpc.c | 1 | ||||
| -rw-r--r-- | include/net/af_rxrpc.h | 1 | ||||
| -rw-r--r-- | net/rxrpc/af_rxrpc.c | 3 | ||||
| -rw-r--r-- | net/rxrpc/ar-internal.h | 2 | ||||
| -rw-r--r-- | net/rxrpc/call_object.c | 2 | ||||
| -rw-r--r-- | net/rxrpc/conn_client.c | 8 | ||||
| -rw-r--r-- | net/rxrpc/sendmsg.c | 4 |
8 files changed, 28 insertions, 4 deletions
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt index ff035a6418e3..180e07d956a7 100644 --- a/Documentation/networking/rxrpc.txt +++ b/Documentation/networking/rxrpc.txt | |||
| @@ -796,7 +796,9 @@ The kernel interface functions are as follows: | |||
| 796 | s64 tx_total_len, | 796 | s64 tx_total_len, |
| 797 | gfp_t gfp, | 797 | gfp_t gfp, |
| 798 | rxrpc_notify_rx_t notify_rx, | 798 | rxrpc_notify_rx_t notify_rx, |
| 799 | bool upgrade); | 799 | bool upgrade, |
| 800 | bool intr, | ||
| 801 | unsigned int debug_id); | ||
| 800 | 802 | ||
| 801 | This allocates the infrastructure to make a new RxRPC call and assigns | 803 | This allocates the infrastructure to make a new RxRPC call and assigns |
| 802 | call and connection numbers. The call will be made on the UDP port that | 804 | call and connection numbers. The call will be made on the UDP port that |
| @@ -824,6 +826,13 @@ The kernel interface functions are as follows: | |||
| 824 | the server upgrade the service to a better one. The resultant service ID | 826 | the server upgrade the service to a better one. The resultant service ID |
| 825 | is returned by rxrpc_kernel_recv_data(). | 827 | is returned by rxrpc_kernel_recv_data(). |
| 826 | 828 | ||
| 829 | intr should be set to true if the call should be interruptible. If this | ||
| 830 | is not set, this function may not return until a channel has been | ||
| 831 | allocated; if it is set, the function may return -ERESTARTSYS. | ||
| 832 | |||
| 833 | debug_id is the call debugging ID to be used for tracing. This can be | ||
| 834 | obtained by atomically incrementing rxrpc_debug_id. | ||
| 835 | |||
| 827 | If this function is successful, an opaque reference to the RxRPC call is | 836 | If this function is successful, an opaque reference to the RxRPC call is |
| 828 | returned. The caller now holds a reference on this and it must be | 837 | returned. The caller now holds a reference on this and it must be |
| 829 | properly ended. | 838 | properly ended. |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 4974defb4592..87763379952d 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -417,6 +417,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp) | |||
| 417 | afs_wake_up_async_call : | 417 | afs_wake_up_async_call : |
| 418 | afs_wake_up_call_waiter), | 418 | afs_wake_up_call_waiter), |
| 419 | call->upgrade, | 419 | call->upgrade, |
| 420 | true, | ||
| 420 | call->debug_id); | 421 | call->debug_id); |
| 421 | if (IS_ERR(rxcall)) { | 422 | if (IS_ERR(rxcall)) { |
| 422 | ret = PTR_ERR(rxcall); | 423 | ret = PTR_ERR(rxcall); |
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index c04602ca4a55..93358bfc0e1b 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h | |||
| @@ -45,6 +45,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *, | |||
| 45 | gfp_t, | 45 | gfp_t, |
| 46 | rxrpc_notify_rx_t, | 46 | rxrpc_notify_rx_t, |
| 47 | bool, | 47 | bool, |
| 48 | bool, | ||
| 48 | unsigned int); | 49 | unsigned int); |
| 49 | int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *, | 50 | int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *, |
| 50 | struct msghdr *, size_t, | 51 | struct msghdr *, size_t, |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 213935fbbbf7..ffde5b187f5d 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -270,6 +270,7 @@ static int rxrpc_listen(struct socket *sock, int backlog) | |||
| 270 | * @gfp: The allocation constraints | 270 | * @gfp: The allocation constraints |
| 271 | * @notify_rx: Where to send notifications instead of socket queue | 271 | * @notify_rx: Where to send notifications instead of socket queue |
| 272 | * @upgrade: Request service upgrade for call | 272 | * @upgrade: Request service upgrade for call |
| 273 | * @intr: The call is interruptible | ||
| 273 | * @debug_id: The debug ID for tracing to be assigned to the call | 274 | * @debug_id: The debug ID for tracing to be assigned to the call |
| 274 | * | 275 | * |
| 275 | * Allow a kernel service to begin a call on the nominated socket. This just | 276 | * Allow a kernel service to begin a call on the nominated socket. This just |
| @@ -287,6 +288,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
| 287 | gfp_t gfp, | 288 | gfp_t gfp, |
| 288 | rxrpc_notify_rx_t notify_rx, | 289 | rxrpc_notify_rx_t notify_rx, |
| 289 | bool upgrade, | 290 | bool upgrade, |
| 291 | bool intr, | ||
| 290 | unsigned int debug_id) | 292 | unsigned int debug_id) |
| 291 | { | 293 | { |
| 292 | struct rxrpc_conn_parameters cp; | 294 | struct rxrpc_conn_parameters cp; |
| @@ -311,6 +313,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
| 311 | memset(&p, 0, sizeof(p)); | 313 | memset(&p, 0, sizeof(p)); |
| 312 | p.user_call_ID = user_call_ID; | 314 | p.user_call_ID = user_call_ID; |
| 313 | p.tx_total_len = tx_total_len; | 315 | p.tx_total_len = tx_total_len; |
| 316 | p.intr = intr; | ||
| 314 | 317 | ||
| 315 | memset(&cp, 0, sizeof(cp)); | 318 | memset(&cp, 0, sizeof(cp)); |
| 316 | cp.local = rx->local; | 319 | cp.local = rx->local; |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 062ca9dc29b8..07fc1dfa4878 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
| @@ -482,6 +482,7 @@ enum rxrpc_call_flag { | |||
| 482 | RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */ | 482 | RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */ |
| 483 | RXRPC_CALL_RX_HEARD, /* The peer responded at least once to this call */ | 483 | RXRPC_CALL_RX_HEARD, /* The peer responded at least once to this call */ |
| 484 | RXRPC_CALL_RX_UNDERRUN, /* Got data underrun */ | 484 | RXRPC_CALL_RX_UNDERRUN, /* Got data underrun */ |
| 485 | RXRPC_CALL_IS_INTR, /* The call is interruptible */ | ||
| 485 | }; | 486 | }; |
| 486 | 487 | ||
| 487 | /* | 488 | /* |
| @@ -711,6 +712,7 @@ struct rxrpc_call_params { | |||
| 711 | u32 normal; /* Max time since last call packet (msec) */ | 712 | u32 normal; /* Max time since last call packet (msec) */ |
| 712 | } timeouts; | 713 | } timeouts; |
| 713 | u8 nr_timeouts; /* Number of timeouts specified */ | 714 | u8 nr_timeouts; /* Number of timeouts specified */ |
| 715 | bool intr; /* The call is interruptible */ | ||
| 714 | }; | 716 | }; |
| 715 | 717 | ||
| 716 | struct rxrpc_send_params { | 718 | struct rxrpc_send_params { |
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index fe96881a334d..d0ca98d7aef5 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
| @@ -241,6 +241,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, | |||
| 241 | return call; | 241 | return call; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | if (p->intr) | ||
| 245 | __set_bit(RXRPC_CALL_IS_INTR, &call->flags); | ||
| 244 | call->tx_total_len = p->tx_total_len; | 246 | call->tx_total_len = p->tx_total_len; |
| 245 | trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), | 247 | trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), |
| 246 | here, (const void *)p->user_call_ID); | 248 | here, (const void *)p->user_call_ID); |
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index 83797b3949e2..5cf5595a14d8 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c | |||
| @@ -656,10 +656,14 @@ static int rxrpc_wait_for_channel(struct rxrpc_call *call, gfp_t gfp) | |||
| 656 | 656 | ||
| 657 | add_wait_queue_exclusive(&call->waitq, &myself); | 657 | add_wait_queue_exclusive(&call->waitq, &myself); |
| 658 | for (;;) { | 658 | for (;;) { |
| 659 | set_current_state(TASK_INTERRUPTIBLE); | 659 | if (test_bit(RXRPC_CALL_IS_INTR, &call->flags)) |
| 660 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 661 | else | ||
| 662 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 660 | if (call->call_id) | 663 | if (call->call_id) |
| 661 | break; | 664 | break; |
| 662 | if (signal_pending(current)) { | 665 | if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) && |
| 666 | signal_pending(current)) { | ||
| 663 | ret = -ERESTARTSYS; | 667 | ret = -ERESTARTSYS; |
| 664 | break; | 668 | break; |
| 665 | } | 669 | } |
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index bec64deb7b0a..45a05d9a27fa 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
| @@ -80,7 +80,8 @@ static int rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx, | |||
| 80 | if (call->state >= RXRPC_CALL_COMPLETE) | 80 | if (call->state >= RXRPC_CALL_COMPLETE) |
| 81 | return call->error; | 81 | return call->error; |
| 82 | 82 | ||
| 83 | if (timeout == 0 && | 83 | if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) && |
| 84 | timeout == 0 && | ||
| 84 | tx_win == tx_start && signal_pending(current)) | 85 | tx_win == tx_start && signal_pending(current)) |
| 85 | return -EINTR; | 86 | return -EINTR; |
| 86 | 87 | ||
| @@ -620,6 +621,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) | |||
| 620 | .call.tx_total_len = -1, | 621 | .call.tx_total_len = -1, |
| 621 | .call.user_call_ID = 0, | 622 | .call.user_call_ID = 0, |
| 622 | .call.nr_timeouts = 0, | 623 | .call.nr_timeouts = 0, |
| 624 | .call.intr = true, | ||
| 623 | .abort_code = 0, | 625 | .abort_code = 0, |
| 624 | .command = RXRPC_CMD_SEND_DATA, | 626 | .command = RXRPC_CMD_SEND_DATA, |
| 625 | .exclusive = false, | 627 | .exclusive = false, |
