Skip to content

Commit 5ac0d62

Browse files
committed
rxrpc: Fix missing notification
Under some circumstances, rxrpc will fail a transmit a packet through the underlying UDP socket (ie. UDP sendmsg returns an error). This may result in a call getting stuck. In the instance being seen, where AFS tries to send a probe to the Volume Location server, tracepoints show the UDP Tx failure (in this case returing error 99 EADDRNOTAVAIL) and then nothing more: afs_make_vl_call: c=0000015d VL.GetCapabilities rxrpc_call: c=0000015d NWc u=1 sp=rxrpc_kernel_begin_call+0x106/0x170 [rxrpc] a=00000000dd89ee8a rxrpc_call: c=0000015d Gus u=2 sp=rxrpc_new_client_call+0x14f/0x580 [rxrpc] a=00000000e20e4b08 rxrpc_call: c=0000015d SEE u=2 sp=rxrpc_activate_one_channel+0x7b/0x1c0 [rxrpc] a=00000000e20e4b08 rxrpc_call: c=0000015d CON u=2 sp=rxrpc_kernel_begin_call+0x106/0x170 [rxrpc] a=00000000e20e4b08 rxrpc_tx_fail: c=0000015d r=1 ret=-99 CallDataNofrag The problem is that if the initial packet fails and the retransmission timer hasn't been started, the call is set to completed and an error is returned from rxrpc_send_data_packet() to rxrpc_queue_packet(). Though rxrpc_instant_resend() is called, this does nothing because the call is marked completed. So rxrpc_notify_socket() isn't called and the error is passed back up to rxrpc_send_data(), rxrpc_kernel_send_data() and thence to afs_make_call() and afs_vl_get_capabilities() where it is simply ignored because it is assumed that the result of a probe will be collected asynchronously. Fileserver probing is similarly affected via afs_fs_get_capabilities(). Fix this by always issuing a notification in __rxrpc_set_call_completion() if it shifts a call to the completed state, even if an error is also returned to the caller through the function return value. Also put in a little bit of optimisation to avoid taking the call state_lock and disabling softirqs if the call is already in the completed state and remove some now redundant rxrpc_notify_socket() calls. Fixes: f5c17aa ("rxrpc: Calls should only have one terminal state") Reported-by: Gerry Seidman <[email protected]> Signed-off-by: David Howells <[email protected]> Reviewed-by: Marc Dionne <[email protected]>
1 parent 3067bf8 commit 5ac0d62

File tree

6 files changed

+21
-25
lines changed

6 files changed

+21
-25
lines changed

net/rxrpc/call_event.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,6 @@ void rxrpc_process_call(struct work_struct *work)
320320

321321
if (call->state == RXRPC_CALL_COMPLETE) {
322322
del_timer_sync(&call->timer);
323-
rxrpc_notify_socket(call);
324323
goto out_put;
325324
}
326325

net/rxrpc/conn_event.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,9 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
173173
else
174174
trace_rxrpc_rx_abort(call, serial,
175175
conn->abort_code);
176-
if (rxrpc_set_call_completion(call, compl,
177-
conn->abort_code,
178-
conn->error))
179-
rxrpc_notify_socket(call);
176+
rxrpc_set_call_completion(call, compl,
177+
conn->abort_code,
178+
conn->error);
180179
}
181180
}
182181

net/rxrpc/input.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
275275

276276
case RXRPC_CALL_SERVER_AWAIT_ACK:
277277
__rxrpc_call_completed(call);
278-
rxrpc_notify_socket(call);
279278
state = call->state;
280279
break;
281280

@@ -1013,9 +1012,8 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb)
10131012

10141013
_proto("Rx ABORT %%%u { %x }", sp->hdr.serial, abort_code);
10151014

1016-
if (rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
1017-
abort_code, -ECONNABORTED))
1018-
rxrpc_notify_socket(call);
1015+
rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
1016+
abort_code, -ECONNABORTED);
10191017
}
10201018

10211019
/*
@@ -1102,7 +1100,6 @@ static void rxrpc_input_implicit_end_call(struct rxrpc_sock *rx,
11021100
spin_lock(&rx->incoming_lock);
11031101
__rxrpc_disconnect_call(conn, call);
11041102
spin_unlock(&rx->incoming_lock);
1105-
rxrpc_notify_socket(call);
11061103
}
11071104

11081105
/*

net/rxrpc/peer_event.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,7 @@ static void rxrpc_distribute_error(struct rxrpc_peer *peer, int error,
289289

290290
hlist_for_each_entry_rcu(call, &peer->error_targets, error_link) {
291291
rxrpc_see_call(call);
292-
if (call->state < RXRPC_CALL_COMPLETE &&
293-
rxrpc_set_call_completion(call, compl, 0, -error))
294-
rxrpc_notify_socket(call);
292+
rxrpc_set_call_completion(call, compl, 0, -error);
295293
}
296294
}
297295

net/rxrpc/recvmsg.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ bool __rxrpc_set_call_completion(struct rxrpc_call *call,
7373
call->state = RXRPC_CALL_COMPLETE;
7474
trace_rxrpc_call_complete(call);
7575
wake_up(&call->waitq);
76+
rxrpc_notify_socket(call);
7677
return true;
7778
}
7879
return false;
@@ -83,11 +84,13 @@ bool rxrpc_set_call_completion(struct rxrpc_call *call,
8384
u32 abort_code,
8485
int error)
8586
{
86-
bool ret;
87+
bool ret = false;
8788

88-
write_lock_bh(&call->state_lock);
89-
ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
90-
write_unlock_bh(&call->state_lock);
89+
if (call->state < RXRPC_CALL_COMPLETE) {
90+
write_lock_bh(&call->state_lock);
91+
ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
92+
write_unlock_bh(&call->state_lock);
93+
}
9194
return ret;
9295
}
9396

@@ -101,11 +104,13 @@ bool __rxrpc_call_completed(struct rxrpc_call *call)
101104

102105
bool rxrpc_call_completed(struct rxrpc_call *call)
103106
{
104-
bool ret;
107+
bool ret = false;
105108

106-
write_lock_bh(&call->state_lock);
107-
ret = __rxrpc_call_completed(call);
108-
write_unlock_bh(&call->state_lock);
109+
if (call->state < RXRPC_CALL_COMPLETE) {
110+
write_lock_bh(&call->state_lock);
111+
ret = __rxrpc_call_completed(call);
112+
write_unlock_bh(&call->state_lock);
113+
}
109114
return ret;
110115
}
111116

net/rxrpc/sendmsg.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,8 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
261261
case -ENETUNREACH:
262262
case -EHOSTUNREACH:
263263
case -ECONNREFUSED:
264-
if (rxrpc_set_call_completion(call,
265-
RXRPC_CALL_LOCAL_ERROR,
266-
0, ret))
267-
rxrpc_notify_socket(call);
264+
rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
265+
0, ret);
268266
goto out;
269267
}
270268
_debug("need instant resend %d", ret);

0 commit comments

Comments
 (0)