summaryrefslogtreecommitdiffstats
path: root/fs/afs/cmservice.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-11-02 11:27:53 -0400
committerDavid Howells <dhowells@redhat.com>2017-11-13 10:38:21 -0500
commit98bf40cd99fcfed0705812b6cbdbb3b441a42970 (patch)
treee0108e6306a6fde29bf7d5348f730922a18dc2b1 /fs/afs/cmservice.c
parent13524ab3c6f41bcd257d28644414297bea8282b7 (diff)
afs: Protect call->state changes against signals
Protect call->state changes against the call being prematurely terminated due to a signal. What can happen is that a signal causes afs_wait_for_call_to_complete() to abort an afs_call because it's not yet complete whilst afs_deliver_to_call() is delivering data to that call. If the data delivery causes the state to change, this may overwrite the state of the afs_call, making it not-yet-complete again - but no further notifications will be forthcoming from AF_RXRPC as the rxrpc call has been aborted and completed, so kAFS will just hang in various places waiting for that call or on page bits that need clearing by that call. A tracepoint to monitor call state changes is also provided. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/cmservice.c')
-rw-r--r--fs/afs/cmservice.c26
1 files changed, 12 insertions, 14 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 5767f540e0e1..41e277f57b20 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -188,7 +188,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
188 188
189 switch (call->unmarshall) { 189 switch (call->unmarshall) {
190 case 0: 190 case 0:
191 rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
192 call->offset = 0; 191 call->offset = 0;
193 call->unmarshall++; 192 call->unmarshall++;
194 193
@@ -281,10 +280,12 @@ static int afs_deliver_cb_callback(struct afs_call *call)
281 break; 280 break;
282 } 281 }
283 282
284 call->state = AFS_CALL_REPLYING; 283 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
284 return -EIO;
285 285
286 /* we'll need the file server record as that tells us which set of 286 /* we'll need the file server record as that tells us which set of
287 * vnodes to operate upon */ 287 * vnodes to operate upon */
288 rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
288 server = afs_find_server(call->net, &srx); 289 server = afs_find_server(call->net, &srx);
289 if (!server) 290 if (!server)
290 return -ENOTCONN; 291 return -ENOTCONN;
@@ -325,9 +326,6 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
325 if (ret < 0) 326 if (ret < 0)
326 return ret; 327 return ret;
327 328
328 /* no unmarshalling required */
329 call->state = AFS_CALL_REPLYING;
330
331 /* we'll need the file server record as that tells us which set of 329 /* we'll need the file server record as that tells us which set of
332 * vnodes to operate upon */ 330 * vnodes to operate upon */
333 server = afs_find_server(call->net, &srx); 331 server = afs_find_server(call->net, &srx);
@@ -352,8 +350,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
352 350
353 _enter(""); 351 _enter("");
354 352
355 rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
356
357 _enter("{%u}", call->unmarshall); 353 _enter("{%u}", call->unmarshall);
358 354
359 switch (call->unmarshall) { 355 switch (call->unmarshall) {
@@ -397,11 +393,12 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
397 break; 393 break;
398 } 394 }
399 395
400 /* no unmarshalling required */ 396 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
401 call->state = AFS_CALL_REPLYING; 397 return -EIO;
402 398
403 /* we'll need the file server record as that tells us which set of 399 /* we'll need the file server record as that tells us which set of
404 * vnodes to operate upon */ 400 * vnodes to operate upon */
401 rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
405 server = afs_find_server(call->net, &srx); 402 server = afs_find_server(call->net, &srx);
406 if (!server) 403 if (!server)
407 return -ENOTCONN; 404 return -ENOTCONN;
@@ -436,8 +433,8 @@ static int afs_deliver_cb_probe(struct afs_call *call)
436 if (ret < 0) 433 if (ret < 0)
437 return ret; 434 return ret;
438 435
439 /* no unmarshalling required */ 436 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
440 call->state = AFS_CALL_REPLYING; 437 return -EIO;
441 438
442 return afs_queue_call_work(call); 439 return afs_queue_call_work(call);
443} 440}
@@ -519,7 +516,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
519 break; 516 break;
520 } 517 }
521 518
522 call->state = AFS_CALL_REPLYING; 519 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
520 return -EIO;
523 521
524 return afs_queue_call_work(call); 522 return afs_queue_call_work(call);
525} 523}
@@ -600,8 +598,8 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
600 if (ret < 0) 598 if (ret < 0)
601 return ret; 599 return ret;
602 600
603 /* no unmarshalling required */ 601 if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
604 call->state = AFS_CALL_REPLYING; 602 return -EIO;
605 603
606 return afs_queue_call_work(call); 604 return afs_queue_call_work(call);
607} 605}