diff --git a/fs/afs/afs_cm.h b/fs/afs/afs_cm.h index d4bd201cc31e..7b4d4fab4c80 100644 --- a/fs/afs/afs_cm.h +++ b/fs/afs/afs_cm.h @@ -23,6 +23,7 @@ enum AFS_CM_Operations { CBGetCE = 208, /* get cache file description */ CBGetXStatsVersion = 209, /* get version of extended statistics */ CBGetXStats = 210, /* get contents of extended statistics data */ + CBInitCallBackState3 = 213, /* initialise callback state, version 3 */ CBGetCapabilities = 65538, /* get client capabilities */ }; diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index a6af3acf016e..6685f4cbccb3 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -20,6 +20,8 @@ struct workqueue_struct *afs_cm_workqueue; static int afs_deliver_cb_init_call_back_state(struct afs_call *, struct sk_buff *, bool); +static int afs_deliver_cb_init_call_back_state3(struct afs_call *, + struct sk_buff *, bool); static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool); static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool); static int afs_deliver_cb_get_capabilities(struct afs_call *, struct sk_buff *, @@ -46,6 +48,16 @@ static const struct afs_call_type afs_SRXCBInitCallBackState = { .destructor = afs_cm_destructor, }; +/* + * CB.InitCallBackState3 operation type + */ +static const struct afs_call_type afs_SRXCBInitCallBackState3 = { + .name = "CB.InitCallBackState3", + .deliver = afs_deliver_cb_init_call_back_state3, + .abort_to_error = afs_abort_to_error, + .destructor = afs_cm_destructor, +}; + /* * CB.Probe operation type */ @@ -83,6 +95,9 @@ bool afs_cm_incoming_call(struct afs_call *call) case CBInitCallBackState: call->type = &afs_SRXCBInitCallBackState; return true; + case CBInitCallBackState3: + call->type = &afs_SRXCBInitCallBackState3; + return true; case CBProbe: call->type = &afs_SRXCBProbe; return true; @@ -311,6 +326,37 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call, return 0; } +/* + * deliver request data to a CB.InitCallBackState3 call + */ +static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, + struct sk_buff *skb, + bool last) +{ + struct afs_server *server; + struct in_addr addr; + + _enter(",{%u},%d", skb->len, last); + + if (!last) + return 0; + + /* no unmarshalling required */ + call->state = AFS_CALL_REPLYING; + + /* we'll need the file server record as that tells us which set of + * vnodes to operate upon */ + memcpy(&addr, &ip_hdr(skb)->saddr, 4); + server = afs_find_server(&addr); + if (!server) + return -ENOTCONN; + call->server = server; + + INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); + schedule_work(&call->work); + return 0; +} + /* * allow the fileserver to see if the cache manager is still alive */