Skip to content

Commit 4aece6a

Browse files
author
Benny Halevy
committed
nfs41: cb_sequence xdr implementation
[nfs41: get rid of READMEM and COPYMEM for callback_xdr.c] Signed-off-by: Benny Halevy <[email protected]> [nfs41: get rid of READ64 in callback_xdr.c] See http://linux-nfs.org/pipermail/pnfs/2009-June/007846.html Signed-off-by: Benny Halevy <[email protected]>
1 parent d49433e commit 4aece6a

File tree

1 file changed

+170
-2
lines changed

1 file changed

+170
-2
lines changed

fs/nfs/callback_xdr.c

+170-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
2 + 2 + 3 + 3)
2121
#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
2222

23+
#if defined(CONFIG_NFS_V4_1)
24+
#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
25+
4 + 1 + 3)
26+
#endif /* CONFIG_NFS_V4_1 */
27+
2328
#define NFSDBG_FACILITY NFSDBG_CALLBACK
2429

2530
typedef __be32 (*callback_process_op_t)(void *, void *);
@@ -207,6 +212,122 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
207212
return status;
208213
}
209214

215+
#if defined(CONFIG_NFS_V4_1)
216+
217+
static unsigned decode_sessionid(struct xdr_stream *xdr,
218+
struct nfs4_sessionid *sid)
219+
{
220+
uint32_t *p;
221+
int len = NFS4_MAX_SESSIONID_LEN;
222+
223+
p = read_buf(xdr, len);
224+
if (unlikely(p == NULL))
225+
return htonl(NFS4ERR_RESOURCE);;
226+
227+
memcpy(sid->data, p, len);
228+
return 0;
229+
}
230+
231+
static unsigned decode_rc_list(struct xdr_stream *xdr,
232+
struct referring_call_list *rc_list)
233+
{
234+
uint32_t *p;
235+
int i;
236+
unsigned status;
237+
238+
status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
239+
if (status)
240+
goto out;
241+
242+
status = htonl(NFS4ERR_RESOURCE);
243+
p = read_buf(xdr, sizeof(uint32_t));
244+
if (unlikely(p == NULL))
245+
goto out;
246+
247+
rc_list->rcl_nrefcalls = ntohl(*p++);
248+
if (rc_list->rcl_nrefcalls) {
249+
p = read_buf(xdr,
250+
rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
251+
if (unlikely(p == NULL))
252+
goto out;
253+
rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
254+
sizeof(*rc_list->rcl_refcalls),
255+
GFP_KERNEL);
256+
if (unlikely(rc_list->rcl_refcalls == NULL))
257+
goto out;
258+
for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
259+
rc_list->rcl_refcalls[i].rc_sequenceid = ntohl(*p++);
260+
rc_list->rcl_refcalls[i].rc_slotid = ntohl(*p++);
261+
}
262+
}
263+
status = 0;
264+
265+
out:
266+
return status;
267+
}
268+
269+
static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
270+
struct xdr_stream *xdr,
271+
struct cb_sequenceargs *args)
272+
{
273+
uint32_t *p;
274+
int i;
275+
unsigned status;
276+
277+
status = decode_sessionid(xdr, &args->csa_sessionid);
278+
if (status)
279+
goto out;
280+
281+
status = htonl(NFS4ERR_RESOURCE);
282+
p = read_buf(xdr, 5 * sizeof(uint32_t));
283+
if (unlikely(p == NULL))
284+
goto out;
285+
286+
args->csa_addr = svc_addr_in(rqstp);
287+
args->csa_sequenceid = ntohl(*p++);
288+
args->csa_slotid = ntohl(*p++);
289+
args->csa_highestslotid = ntohl(*p++);
290+
args->csa_cachethis = ntohl(*p++);
291+
args->csa_nrclists = ntohl(*p++);
292+
args->csa_rclists = NULL;
293+
if (args->csa_nrclists) {
294+
args->csa_rclists = kmalloc(args->csa_nrclists *
295+
sizeof(*args->csa_rclists),
296+
GFP_KERNEL);
297+
if (unlikely(args->csa_rclists == NULL))
298+
goto out;
299+
300+
for (i = 0; i < args->csa_nrclists; i++) {
301+
status = decode_rc_list(xdr, &args->csa_rclists[i]);
302+
if (status)
303+
goto out_free;
304+
}
305+
}
306+
status = 0;
307+
308+
dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
309+
"highestslotid %u cachethis %d nrclists %u\n",
310+
__func__,
311+
((u32 *)&args->csa_sessionid)[0],
312+
((u32 *)&args->csa_sessionid)[1],
313+
((u32 *)&args->csa_sessionid)[2],
314+
((u32 *)&args->csa_sessionid)[3],
315+
args->csa_sequenceid, args->csa_slotid,
316+
args->csa_highestslotid, args->csa_cachethis,
317+
args->csa_nrclists);
318+
out:
319+
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
320+
return status;
321+
322+
out_free:
323+
for (i = 0; i < args->csa_nrclists; i++)
324+
kfree(args->csa_rclists[i].rcl_refcalls);
325+
kfree(args->csa_rclists);
326+
goto out;
327+
}
328+
329+
#endif /* CONFIG_NFS_V4_1 */
330+
210331
static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
211332
{
212333
__be32 *p;
@@ -358,12 +479,52 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
358479

359480
#if defined(CONFIG_NFS_V4_1)
360481

482+
static unsigned encode_sessionid(struct xdr_stream *xdr,
483+
const struct nfs4_sessionid *sid)
484+
{
485+
uint32_t *p;
486+
int len = NFS4_MAX_SESSIONID_LEN;
487+
488+
p = xdr_reserve_space(xdr, len);
489+
if (unlikely(p == NULL))
490+
return htonl(NFS4ERR_RESOURCE);
491+
492+
memcpy(p, sid, len);
493+
return 0;
494+
}
495+
496+
static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp,
497+
struct xdr_stream *xdr,
498+
const struct cb_sequenceres *res)
499+
{
500+
uint32_t *p;
501+
unsigned status = res->csr_status;
502+
503+
if (unlikely(status != 0))
504+
goto out;
505+
506+
encode_sessionid(xdr, &res->csr_sessionid);
507+
508+
p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
509+
if (unlikely(p == NULL))
510+
return htonl(NFS4ERR_RESOURCE);
511+
512+
*p++ = htonl(res->csr_sequenceid);
513+
*p++ = htonl(res->csr_slotid);
514+
*p++ = htonl(res->csr_highestslotid);
515+
*p++ = htonl(res->csr_target_highestslotid);
516+
out:
517+
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
518+
return status;
519+
}
520+
361521
static __be32
362522
preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
363523
{
364524
switch (op_nr) {
365525
case OP_CB_GETATTR:
366526
case OP_CB_RECALL:
527+
case OP_CB_SEQUENCE:
367528
*op = &callback_ops[op_nr];
368529
break;
369530

@@ -374,7 +535,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
374535
case OP_CB_RECALL_ANY:
375536
case OP_CB_RECALLABLE_OBJ_AVAIL:
376537
case OP_CB_RECALL_SLOT:
377-
case OP_CB_SEQUENCE:
378538
case OP_CB_WANTS_CANCELLED:
379539
case OP_CB_NOTIFY_LOCK:
380540
return htonl(NFS4ERR_NOTSUPP);
@@ -512,7 +672,15 @@ static struct callback_op callback_ops[] = {
512672
.process_op = (callback_process_op_t)nfs4_callback_recall,
513673
.decode_args = (callback_decode_arg_t)decode_recall_args,
514674
.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
515-
}
675+
},
676+
#if defined(CONFIG_NFS_V4_1)
677+
[OP_CB_SEQUENCE] = {
678+
.process_op = (callback_process_op_t)nfs4_callback_sequence,
679+
.decode_args = (callback_decode_arg_t)decode_cb_sequence_args,
680+
.encode_res = (callback_encode_res_t)encode_cb_sequence_res,
681+
.res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
682+
},
683+
#endif /* CONFIG_NFS_V4_1 */
516684
};
517685

518686
/*

0 commit comments

Comments
 (0)