Skip to content

Commit

Permalink
afs: Fix CB.CallBack handling
Browse files Browse the repository at this point in the history
The handling of CB.CallBack messages sent by the fileserver to the client
is broken in that they are currently being processed after the reply has
been transmitted.

This is not what the fileserver expects, however.  It holds up change
visibility until the reply comes so as to maintain cache coherency, and so
expects the client to have to refetch the state on the affected files.

Fix CB.CallBack handling to perform the callback break before sending the
reply.

The fileserver is free to hold up status fetches issued by other threads on
the same client that occur in reponse to the callback until any pending
changes have been committed.

Fixes: d001648 ("rxrpc: Don't expose skbs to in-kernel users [ver #2]")
Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed May 14, 2018
1 parent 68251f0 commit 428edad
Showing 1 changed file with 7 additions and 28 deletions.
35 changes: 7 additions & 28 deletions fs/afs/cmservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,10 @@ bool afs_cm_incoming_call(struct afs_call *call)
}

/*
* clean up a cache manager call
* Clean up a cache manager call.
*/
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->cm_server && call->unmarshall == 5) {
ASSERT(call->count && call->request);
afs_break_callbacks(call->cm_server, call->count, call->request);
}

kfree(call->buffer);
call->buffer = NULL;
}
Expand All @@ -161,15 +150,14 @@ static void SRXAFSCB_CallBack(struct work_struct *work)

_enter("");

/* be sure to send the reply *before* attempting to spam the AFS server
* with FSFetchStatus requests on the vnodes with broken callbacks lest
* the AFS server get into a vicious cycle of trying to break further
* callbacks because it hadn't received completion of the CBCallBack op
* yet */
afs_send_empty_reply(call);

/* We need to break the callbacks before sending the reply as the
* server holds up change visibility till it receives our reply so as
* to maintain cache coherency.
*/
if (call->cm_server)
afs_break_callbacks(call->cm_server, call->count, call->request);

afs_send_empty_reply(call);
afs_put_call(call);
_leave("");
}
Expand Down Expand Up @@ -267,15 +255,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)

call->offset = 0;
call->unmarshall++;

/* 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 5:
break;
}
Expand Down

0 comments on commit 428edad

Please sign in to comment.