Skip to content

Commit 35dbfba

Browse files
committed
afs: Implement the YFS cache manager service
Implement the YFS cache manager service which gives extra capabilities on top of AFS. This is done by listening for an additional service on the same port and indicating that anyone requesting an upgrade should be upgraded to the YFS port. Signed-off-by: David Howells <[email protected]>
1 parent 06aeb29 commit 35dbfba

File tree

3 files changed

+174
-1
lines changed

3 files changed

+174
-1
lines changed

fs/afs/cmservice.c

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/ip.h>
1717
#include "internal.h"
1818
#include "afs_cm.h"
19+
#include "protocol_yfs.h"
1920

2021
static int afs_deliver_cb_init_call_back_state(struct afs_call *);
2122
static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
@@ -30,6 +31,8 @@ static void SRXAFSCB_Probe(struct work_struct *);
3031
static void SRXAFSCB_ProbeUuid(struct work_struct *);
3132
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
3233

34+
static int afs_deliver_yfs_cb_callback(struct afs_call *);
35+
3336
#define CM_NAME(name) \
3437
const char afs_SRXCB##name##_name[] __tracepoint_string = \
3538
"CB." #name
@@ -100,13 +103,24 @@ static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
100103
.work = SRXAFSCB_TellMeAboutYourself,
101104
};
102105

106+
/*
107+
* YFS CB.CallBack operation type
108+
*/
109+
static CM_NAME(YFS_CallBack);
110+
static const struct afs_call_type afs_SRXYFSCB_CallBack = {
111+
.name = afs_SRXCBYFS_CallBack_name,
112+
.deliver = afs_deliver_yfs_cb_callback,
113+
.destructor = afs_cm_destructor,
114+
.work = SRXAFSCB_CallBack,
115+
};
116+
103117
/*
104118
* route an incoming cache manager call
105119
* - return T if supported, F if not
106120
*/
107121
bool afs_cm_incoming_call(struct afs_call *call)
108122
{
109-
_enter("{CB.OP %u}", call->operation_ID);
123+
_enter("{%u, CB.OP %u}", call->service_id, call->operation_ID);
110124

111125
switch (call->operation_ID) {
112126
case CBCallBack:
@@ -127,6 +141,11 @@ bool afs_cm_incoming_call(struct afs_call *call)
127141
case CBTellMeAboutYourself:
128142
call->type = &afs_SRXCBTellMeAboutYourself;
129143
return true;
144+
case YFSCBCallBack:
145+
if (call->service_id != YFS_CM_SERVICE)
146+
return false;
147+
call->type = &afs_SRXYFSCB_CallBack;
148+
return true;
130149
default:
131150
return false;
132151
}
@@ -570,3 +589,85 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
570589

571590
return afs_queue_call_work(call);
572591
}
592+
593+
/*
594+
* deliver request data to a YFS CB.CallBack call
595+
*/
596+
static int afs_deliver_yfs_cb_callback(struct afs_call *call)
597+
{
598+
struct afs_callback_break *cb;
599+
struct sockaddr_rxrpc srx;
600+
struct yfs_xdr_YFSFid *bp;
601+
size_t size;
602+
int ret, loop;
603+
604+
_enter("{%u}", call->unmarshall);
605+
606+
switch (call->unmarshall) {
607+
case 0:
608+
afs_extract_to_tmp(call);
609+
call->unmarshall++;
610+
611+
/* extract the FID array and its count in two steps */
612+
case 1:
613+
_debug("extract FID count");
614+
ret = afs_extract_data(call, true);
615+
if (ret < 0)
616+
return ret;
617+
618+
call->count = ntohl(call->tmp);
619+
_debug("FID count: %u", call->count);
620+
if (call->count > YFSCBMAX)
621+
return afs_protocol_error(call, -EBADMSG,
622+
afs_eproto_cb_fid_count);
623+
624+
size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid));
625+
call->buffer = kmalloc(size, GFP_KERNEL);
626+
if (!call->buffer)
627+
return -ENOMEM;
628+
afs_extract_to_buf(call, size);
629+
call->unmarshall++;
630+
631+
case 2:
632+
_debug("extract FID array");
633+
ret = afs_extract_data(call, false);
634+
if (ret < 0)
635+
return ret;
636+
637+
_debug("unmarshall FID array");
638+
call->request = kcalloc(call->count,
639+
sizeof(struct afs_callback_break),
640+
GFP_KERNEL);
641+
if (!call->request)
642+
return -ENOMEM;
643+
644+
cb = call->request;
645+
bp = call->buffer;
646+
for (loop = call->count; loop > 0; loop--, cb++) {
647+
cb->fid.vid = xdr_to_u64(bp->volume);
648+
cb->fid.vnode = xdr_to_u64(bp->vnode.lo);
649+
cb->fid.vnode_hi = ntohl(bp->vnode.hi);
650+
cb->fid.unique = ntohl(bp->vnode.unique);
651+
bp++;
652+
}
653+
654+
afs_extract_to_tmp(call);
655+
call->unmarshall++;
656+
657+
case 3:
658+
break;
659+
}
660+
661+
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
662+
return afs_io_error(call, afs_io_error_cm_reply);
663+
664+
/* We'll need the file server record as that tells us which set of
665+
* vnodes to operate upon.
666+
*/
667+
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
668+
call->cm_server = afs_find_server(call->net, &srx);
669+
if (!call->cm_server)
670+
trace_afs_cm_no_server(call, &srx);
671+
672+
return afs_queue_call_work(call);
673+
}

fs/afs/protocol_yfs.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* YFS protocol bits
2+
*
3+
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
4+
* Written by David Howells ([email protected])
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public Licence
8+
* as published by the Free Software Foundation; either version
9+
* 2 of the Licence, or (at your option) any later version.
10+
*/
11+
12+
#define YFS_FS_SERVICE 2500
13+
#define YFS_CM_SERVICE 2501
14+
15+
#define YFSCBMAX 1024
16+
17+
enum YFS_CM_Operations {
18+
YFSCBProbe = 206, /* probe client */
19+
YFSCBGetLock = 207, /* get contents of CM lock table */
20+
YFSCBXStatsVersion = 209, /* get version of extended statistics */
21+
YFSCBGetXStats = 210, /* get contents of extended statistics data */
22+
YFSCBInitCallBackState3 = 213, /* initialise callback state, version 3 */
23+
YFSCBProbeUuid = 214, /* check the client hasn't rebooted */
24+
YFSCBGetServerPrefs = 215,
25+
YFSCBGetCellServDV = 216,
26+
YFSCBGetLocalCell = 217,
27+
YFSCBGetCacheConfig = 218,
28+
YFSCBGetCellByNum = 65537,
29+
YFSCBTellMeAboutYourself = 65538, /* get client capabilities */
30+
YFSCBCallBack = 64204,
31+
};
32+
33+
struct yfs_xdr_u64 {
34+
__be32 msw;
35+
__be32 lsw;
36+
} __packed;
37+
38+
static inline u64 xdr_to_u64(const struct yfs_xdr_u64 x)
39+
{
40+
return ((u64)ntohl(x.msw) << 32) | ntohl(x.lsw);
41+
}
42+
43+
static inline struct yfs_xdr_u64 u64_to_xdr(const u64 x)
44+
{
45+
return (struct yfs_xdr_u64){ .msw = htonl(x >> 32), .lsw = htonl(x) };
46+
}
47+
48+
struct yfs_xdr_vnode {
49+
struct yfs_xdr_u64 lo;
50+
__be32 hi;
51+
__be32 unique;
52+
} __packed;
53+
54+
struct yfs_xdr_YFSFid {
55+
struct yfs_xdr_u64 volume;
56+
struct yfs_xdr_vnode vnode;
57+
} __packed;

fs/afs/rxrpc.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/af_rxrpc.h>
1717
#include "internal.h"
1818
#include "afs_cm.h"
19+
#include "protocol_yfs.h"
1920

2021
struct workqueue_struct *afs_async_calls;
2122

@@ -42,6 +43,7 @@ int afs_open_socket(struct afs_net *net)
4243
struct sockaddr_rxrpc srx;
4344
struct socket *socket;
4445
unsigned int min_level;
46+
u16 service_upgrade[2];
4547
int ret;
4648

4749
_enter("");
@@ -75,6 +77,19 @@ int afs_open_socket(struct afs_net *net)
7577
if (ret < 0)
7678
goto error_2;
7779

80+
srx.srx_service = YFS_CM_SERVICE;
81+
ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
82+
if (ret < 0)
83+
goto error_2;
84+
85+
service_upgrade[0] = CM_SERVICE;
86+
service_upgrade[1] = YFS_CM_SERVICE;
87+
ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_UPGRADEABLE_SERVICE,
88+
(void *)service_upgrade, sizeof(service_upgrade));
89+
if (ret < 0)
90+
goto error_2;
91+
92+
7893
rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
7994
afs_rx_discard_new_call);
8095

0 commit comments

Comments
 (0)