diff options
Diffstat (limited to 'fs/afs/cmservice.c')
| -rw-r--r-- | fs/afs/cmservice.c | 31 | 
1 files changed, 25 insertions, 6 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index a3bcec75c54..4b0eff6da67 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -130,6 +130,15 @@ static void afs_cm_destructor(struct afs_call *call)  {  	_enter(""); +	/* Break the callbacks here so that we do it after the final ACK is +	 * received.  The step number here must match the final number in +	 * afs_deliver_cb_callback(). +	 */ +	if (call->unmarshall == 6) { +		ASSERT(call->server && call->count && call->request); +		afs_break_callbacks(call->server, call->count, call->request); +	} +  	afs_put_server(call->server);  	call->server = NULL;  	kfree(call->buffer); @@ -272,6 +281,16 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,  		_debug("trailer");  		if (skb->len != 0)  			return -EBADMSG; + +		/* Record that the message was unmarshalled successfully so +		 * that the call destructor can know do the callback breaking +		 * work, even if the final ACK isn't received. +		 * +		 * If the step number changes, then afs_cm_destructor() must be +		 * updated also. +		 */ +		call->unmarshall++; +	case 6:  		break;  	} @@ -289,7 +308,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,  	call->server = server;  	INIT_WORK(&call->work, SRXAFSCB_CallBack); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  } @@ -336,7 +355,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,  	call->server = server;  	INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  } @@ -367,7 +386,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,  	call->server = server;  	INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  } @@ -400,7 +419,7 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,  	call->state = AFS_CALL_REPLYING;  	INIT_WORK(&call->work, SRXAFSCB_Probe); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  } @@ -496,7 +515,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,  	call->state = AFS_CALL_REPLYING;  	INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  } @@ -580,6 +599,6 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,  	call->state = AFS_CALL_REPLYING;  	INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); -	schedule_work(&call->work); +	queue_work(afs_wq, &call->work);  	return 0;  }  | 
