afs: Fix the handling of an unfound server in CM operations

If the client cache manager operations that need the server record
(CB.Callback, CB.InitCallBackState, and CB.InitCallBackState3) can't find
the server record, they abort the call from the file server with
RX_CALL_DEAD when they should return okay.

Fixes: c35eccb1f6 ("[AFS]: Implement the CB.InitCallBackState3 operation.")
Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells 2018-05-11 23:45:40 +01:00
parent 3709a399c1
commit a86b06d1cc
2 changed files with 12 additions and 27 deletions

View File

@ -143,8 +143,8 @@ static void afs_cm_destructor(struct afs_call *call)
* received. The step number here must match the final number in
* afs_deliver_cb_callback().
*/
if (call->unmarshall == 5) {
ASSERT(call->cm_server && call->count && call->request);
if (call->cm_server && call->unmarshall == 5) {
ASSERT(call->count && call->request);
afs_break_callbacks(call->cm_server, call->count, call->request);
}
@ -168,7 +168,8 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
* yet */
afs_send_empty_reply(call);
afs_break_callbacks(call->cm_server, call->count, call->request);
if (call->cm_server)
afs_break_callbacks(call->cm_server, call->count, call->request);
afs_put_call(call);
_leave("");
}
@ -180,7 +181,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
{
struct afs_callback_break *cb;
struct sockaddr_rxrpc srx;
struct afs_server *server;
__be32 *bp;
int ret, loop;
@ -286,12 +286,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
server = afs_find_server(call->net, &srx);
if (!server) {
call->cm_server = afs_find_server(call->net, &srx);
if (!call->cm_server)
trace_afs_cm_no_server(call, &srx);
return -ENOTCONN;
}
call->cm_server = server;
return afs_queue_call_work(call);
}
@ -305,7 +302,8 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
_enter("{%p}", call->cm_server);
afs_init_callback_state(call->cm_server);
if (call->cm_server)
afs_init_callback_state(call->cm_server);
afs_send_empty_reply(call);
afs_put_call(call);
_leave("");
@ -317,7 +315,6 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
{
struct sockaddr_rxrpc srx;
struct afs_server *server;
int ret;
_enter("");
@ -330,12 +327,9 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
server = afs_find_server(call->net, &srx);
if (!server) {
call->cm_server = afs_find_server(call->net, &srx);
if (!call->cm_server)
trace_afs_cm_no_server(call, &srx);
return -ENOTCONN;
}
call->cm_server = server;
return afs_queue_call_work(call);
}
@ -345,7 +339,6 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
*/
static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
{
struct afs_server *server;
struct afs_uuid *r;
unsigned loop;
__be32 *b;
@ -402,13 +395,10 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
/* we'll need the file server record as that tells us which set of
* vnodes to operate upon */
rcu_read_lock();
server = afs_find_server_by_uuid(call->net, call->request);
call->cm_server = afs_find_server_by_uuid(call->net, call->request);
rcu_read_unlock();
if (!server) {
if (!call->cm_server)
trace_afs_cm_no_server_u(call, call->request);
return -ENOTCONN;
}
call->cm_server = server;
return afs_queue_call_work(call);
}

View File

@ -497,11 +497,6 @@ static void afs_deliver_to_call(struct afs_call *call)
case -ECONNABORTED:
ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
goto done;
case -ENOTCONN:
abort_code = RX_CALL_DEAD;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
abort_code, ret, "KNC");
goto local_abort;
case -ENOTSUPP:
abort_code = RXGEN_OPCODE;
rxrpc_kernel_abort_call(call->net->socket, call->rxcall,