aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2009-04-01 09:23:26 -0400
committerBenny Halevy <bhalevy@panasas.com>2009-06-17 17:11:38 -0400
commit4aece6a19cf7f474f15eb861ba74db4479884ce3 (patch)
tree2ae1c88b163ec78b3cb012319f9881b8db69c810
parentd49433e1e3bb144a5752ce2a8ba1139dc519df1a (diff)
nfs41: cb_sequence xdr implementation
[nfs41: get rid of READMEM and COPYMEM for callback_xdr.c] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [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 <bhalevy@panasas.com>
-rw-r--r--fs/nfs/callback_xdr.c172
1 files changed, 170 insertions, 2 deletions
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 41c5be1c1be5..56a3cc510107 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -20,6 +20,11 @@
20 2 + 2 + 3 + 3) 20 2 + 2 + 3 + 3)
21#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) 21#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
22 22
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
23#define NFSDBG_FACILITY NFSDBG_CALLBACK 28#define NFSDBG_FACILITY NFSDBG_CALLBACK
24 29
25typedef __be32 (*callback_process_op_t)(void *, void *); 30typedef __be32 (*callback_process_op_t)(void *, void *);
@@ -207,6 +212,122 @@ out:
207 return status; 212 return status;
208} 213}
209 214
215#if defined(CONFIG_NFS_V4_1)
216
217static 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
231static 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
265out:
266 return status;
267}
268
269static 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);
318out:
319 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
320 return status;
321
322out_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
210static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str) 331static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
211{ 332{
212 __be32 *p; 333 __be32 *p;
@@ -358,12 +479,52 @@ out:
358 479
359#if defined(CONFIG_NFS_V4_1) 480#if defined(CONFIG_NFS_V4_1)
360 481
482static 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
496static 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);
516out:
517 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
518 return status;
519}
520
361static __be32 521static __be32
362preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op) 522preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
363{ 523{
364 switch (op_nr) { 524 switch (op_nr) {
365 case OP_CB_GETATTR: 525 case OP_CB_GETATTR:
366 case OP_CB_RECALL: 526 case OP_CB_RECALL:
527 case OP_CB_SEQUENCE:
367 *op = &callback_ops[op_nr]; 528 *op = &callback_ops[op_nr];
368 break; 529 break;
369 530
@@ -374,7 +535,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
374 case OP_CB_RECALL_ANY: 535 case OP_CB_RECALL_ANY:
375 case OP_CB_RECALLABLE_OBJ_AVAIL: 536 case OP_CB_RECALLABLE_OBJ_AVAIL:
376 case OP_CB_RECALL_SLOT: 537 case OP_CB_RECALL_SLOT:
377 case OP_CB_SEQUENCE:
378 case OP_CB_WANTS_CANCELLED: 538 case OP_CB_WANTS_CANCELLED:
379 case OP_CB_NOTIFY_LOCK: 539 case OP_CB_NOTIFY_LOCK:
380 return htonl(NFS4ERR_NOTSUPP); 540 return htonl(NFS4ERR_NOTSUPP);
@@ -512,7 +672,15 @@ static struct callback_op callback_ops[] = {
512 .process_op = (callback_process_op_t)nfs4_callback_recall, 672 .process_op = (callback_process_op_t)nfs4_callback_recall,
513 .decode_args = (callback_decode_arg_t)decode_recall_args, 673 .decode_args = (callback_decode_arg_t)decode_recall_args,
514 .res_maxsize = CB_OP_RECALL_RES_MAXSZ, 674 .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 */
516}; 684};
517 685
518/* 686/*