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 /net/rxrpc | |
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>
Diffstat (limited to 'net/rxrpc')
-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 |
5 files changed, 16 insertions, 3 deletions
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, |