Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+28 -4
+10 -1
Documentation/networking/rxrpc.txt
··· 796 796 s64 tx_total_len, 797 797 gfp_t gfp, 798 798 rxrpc_notify_rx_t notify_rx, 799 - bool upgrade); 799 + bool upgrade, 800 + bool intr, 801 + unsigned int debug_id); 800 802 801 803 This allocates the infrastructure to make a new RxRPC call and assigns 802 804 call and connection numbers. The call will be made on the UDP port that ··· 825 823 upgrade should be set to true if a client operation should request that 826 824 the server upgrade the service to a better one. The resultant service ID 827 825 is returned by rxrpc_kernel_recv_data(). 826 + 827 + intr should be set to true if the call should be interruptible. If this 828 + is not set, this function may not return until a channel has been 829 + allocated; if it is set, the function may return -ERESTARTSYS. 830 + 831 + debug_id is the call debugging ID to be used for tracing. This can be 832 + obtained by atomically incrementing rxrpc_debug_id. 828 833 829 834 If this function is successful, an opaque reference to the RxRPC call is 830 835 returned. The caller now holds a reference on this and it must be
+1
fs/afs/rxrpc.c
··· 417 417 afs_wake_up_async_call : 418 418 afs_wake_up_call_waiter), 419 419 call->upgrade, 420 + true, 420 421 call->debug_id); 421 422 if (IS_ERR(rxcall)) { 422 423 ret = PTR_ERR(rxcall);
+1
include/net/af_rxrpc.h
··· 45 45 gfp_t, 46 46 rxrpc_notify_rx_t, 47 47 bool, 48 + bool, 48 49 unsigned int); 49 50 int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *, 50 51 struct msghdr *, size_t,
+3
net/rxrpc/af_rxrpc.c
··· 270 270 * @gfp: The allocation constraints 271 271 * @notify_rx: Where to send notifications instead of socket queue 272 272 * @upgrade: Request service upgrade for call 273 + * @intr: The call is interruptible 273 274 * @debug_id: The debug ID for tracing to be assigned to the call 274 275 * 275 276 * Allow a kernel service to begin a call on the nominated socket. This just ··· 288 287 gfp_t gfp, 289 288 rxrpc_notify_rx_t notify_rx, 290 289 bool upgrade, 290 + bool intr, 291 291 unsigned int debug_id) 292 292 { 293 293 struct rxrpc_conn_parameters cp; ··· 313 311 memset(&p, 0, sizeof(p)); 314 312 p.user_call_ID = user_call_ID; 315 313 p.tx_total_len = tx_total_len; 314 + p.intr = intr; 316 315 317 316 memset(&cp, 0, sizeof(cp)); 318 317 cp.local = rx->local;
+2
net/rxrpc/ar-internal.h
··· 482 482 RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */ 483 483 RXRPC_CALL_RX_HEARD, /* The peer responded at least once to this call */ 484 484 RXRPC_CALL_RX_UNDERRUN, /* Got data underrun */ 485 + RXRPC_CALL_IS_INTR, /* The call is interruptible */ 485 486 }; 486 487 487 488 /* ··· 712 711 u32 normal; /* Max time since last call packet (msec) */ 713 712 } timeouts; 714 713 u8 nr_timeouts; /* Number of timeouts specified */ 714 + bool intr; /* The call is interruptible */ 715 715 }; 716 716 717 717 struct rxrpc_send_params {
+2
net/rxrpc/call_object.c
··· 241 241 return call; 242 242 } 243 243 244 + if (p->intr) 245 + __set_bit(RXRPC_CALL_IS_INTR, &call->flags); 244 246 call->tx_total_len = p->tx_total_len; 245 247 trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage), 246 248 here, (const void *)p->user_call_ID);
+6 -2
net/rxrpc/conn_client.c
··· 656 656 657 657 add_wait_queue_exclusive(&call->waitq, &myself); 658 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 663 if (call->call_id) 661 664 break; 662 - if (signal_pending(current)) { 665 + if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) && 666 + signal_pending(current)) { 663 667 ret = -ERESTARTSYS; 664 668 break; 665 669 }
+3 -1
net/rxrpc/sendmsg.c
··· 80 80 if (call->state >= RXRPC_CALL_COMPLETE) 81 81 return call->error; 82 82 83 - if (timeout == 0 && 83 + if (test_bit(RXRPC_CALL_IS_INTR, &call->flags) && 84 + timeout == 0 && 84 85 tx_win == tx_start && signal_pending(current)) 85 86 return -EINTR; 86 87 ··· 621 620 .call.tx_total_len = -1, 622 621 .call.user_call_ID = 0, 623 622 .call.nr_timeouts = 0, 623 + .call.intr = true, 624 624 .abort_code = 0, 625 625 .command = RXRPC_CMD_SEND_DATA, 626 626 .exclusive = false,