aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-05-11 19:28:58 -0400
committerDavid Howells <dhowells@redhat.com>2018-05-14 10:15:19 -0400
commit428edade4e6c70e5b51fcd4188d944fbb744d84c (patch)
treed2716cea9442e5bdddca00c6bc840d8f6bb977d5
parent68251f0a6818f3be19b1471f36c956ca97c1427d (diff)
afs: Fix CB.CallBack handling
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: d001648ec7cf ("rxrpc: Don't expose skbs to in-kernel users [ver #2]") Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--fs/afs/cmservice.c35
1 files changed, 7 insertions, 28 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index b44491410af3..c332c95a6940 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -133,21 +133,10 @@ bool afs_cm_incoming_call(struct afs_call *call)
133} 133}
134 134
135/* 135/*
136 * clean up a cache manager call 136 * Clean up a cache manager call.
137 */ 137 */
138static void afs_cm_destructor(struct afs_call *call) 138static void afs_cm_destructor(struct afs_call *call)
139{ 139{
140 _enter("");
141
142 /* Break the callbacks here so that we do it after the final ACK is
143 * received. The step number here must match the final number in
144 * afs_deliver_cb_callback().
145 */
146 if (call->cm_server && call->unmarshall == 5) {
147 ASSERT(call->count && call->request);
148 afs_break_callbacks(call->cm_server, call->count, call->request);
149 }
150
151 kfree(call->buffer); 140 kfree(call->buffer);
152 call->buffer = NULL; 141 call->buffer = NULL;
153} 142}
@@ -161,15 +150,14 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
161 150
162 _enter(""); 151 _enter("");
163 152
164 /* be sure to send the reply *before* attempting to spam the AFS server 153 /* We need to break the callbacks before sending the reply as the
165 * with FSFetchStatus requests on the vnodes with broken callbacks lest 154 * server holds up change visibility till it receives our reply so as
166 * the AFS server get into a vicious cycle of trying to break further 155 * to maintain cache coherency.
167 * callbacks because it hadn't received completion of the CBCallBack op 156 */
168 * yet */
169 afs_send_empty_reply(call);
170
171 if (call->cm_server) 157 if (call->cm_server)
172 afs_break_callbacks(call->cm_server, call->count, call->request); 158 afs_break_callbacks(call->cm_server, call->count, call->request);
159
160 afs_send_empty_reply(call);
173 afs_put_call(call); 161 afs_put_call(call);
174 _leave(""); 162 _leave("");
175} 163}
@@ -267,15 +255,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
267 255
268 call->offset = 0; 256 call->offset = 0;
269 call->unmarshall++; 257 call->unmarshall++;
270
271 /* Record that the message was unmarshalled successfully so
272 * that the call destructor can know do the callback breaking
273 * work, even if the final ACK isn't received.
274 *
275 * If the step number changes, then afs_cm_destructor() must be
276 * updated also.
277 */
278 call->unmarshall++;
279 case 5: 258 case 5:
280 break; 259 break;
281 } 260 }