diff options
author | Weston Andros Adamson <dros@netapp.com> | 2011-03-24 16:48:21 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-24 17:01:41 -0400 |
commit | 35124a0994fc02545b14b9fa3aad000b3331f1c0 (patch) | |
tree | 5149267f387199fd9ca2718c74d86b6779013501 /fs/nfs/nfs4filelayout.c | |
parent | ef31153786bc1e4304e6b9422cc8b9efef455611 (diff) |
Cleanup XDR parsing for LAYOUTGET, GETDEVICEINFO
changes LAYOUTGET and GETDEVICEINFO XDR parsing to:
- not use vmap, which doesn't work on incoherent archs
- use xdr_stream parsing for all xdr
Signed-off-by: Weston Andros Adamson <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4filelayout.c')
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index ffb54a082f3a..6f8192f4cfc7 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -502,12 +502,33 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
502 | struct nfs4_layoutget_res *lgr, | 502 | struct nfs4_layoutget_res *lgr, |
503 | struct nfs4_deviceid *id) | 503 | struct nfs4_deviceid *id) |
504 | { | 504 | { |
505 | uint32_t *p = (uint32_t *)lgr->layout.buf; | 505 | struct xdr_stream stream; |
506 | struct xdr_buf buf = { | ||
507 | .pages = lgr->layoutp->pages, | ||
508 | .page_len = lgr->layoutp->len, | ||
509 | .buflen = lgr->layoutp->len, | ||
510 | .len = lgr->layoutp->len, | ||
511 | }; | ||
512 | struct page *scratch; | ||
513 | __be32 *p; | ||
506 | uint32_t nfl_util; | 514 | uint32_t nfl_util; |
507 | int i; | 515 | int i; |
508 | 516 | ||
509 | dprintk("%s: set_layout_map Begin\n", __func__); | 517 | dprintk("%s: set_layout_map Begin\n", __func__); |
510 | 518 | ||
519 | scratch = alloc_page(GFP_KERNEL); | ||
520 | if (!scratch) | ||
521 | return -ENOMEM; | ||
522 | |||
523 | xdr_init_decode(&stream, &buf, NULL); | ||
524 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); | ||
525 | |||
526 | /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8), | ||
527 | * num_fh (4) */ | ||
528 | p = xdr_inline_decode(&stream, NFS4_DEVICEID4_SIZE + 20); | ||
529 | if (unlikely(!p)) | ||
530 | goto out_err; | ||
531 | |||
511 | memcpy(id, p, sizeof(*id)); | 532 | memcpy(id, p, sizeof(*id)); |
512 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | 533 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); |
513 | print_deviceid(id); | 534 | print_deviceid(id); |
@@ -529,32 +550,46 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
529 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, | 550 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, |
530 | fl->pattern_offset); | 551 | fl->pattern_offset); |
531 | 552 | ||
553 | if (!fl->num_fh) | ||
554 | goto out_err; | ||
555 | |||
532 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 556 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
533 | GFP_KERNEL); | 557 | GFP_KERNEL); |
534 | if (!fl->fh_array) | 558 | if (!fl->fh_array) |
535 | return -ENOMEM; | 559 | goto out_err; |
536 | 560 | ||
537 | for (i = 0; i < fl->num_fh; i++) { | 561 | for (i = 0; i < fl->num_fh; i++) { |
538 | /* Do we want to use a mempool here? */ | 562 | /* Do we want to use a mempool here? */ |
539 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); | 563 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); |
540 | if (!fl->fh_array[i]) { | 564 | if (!fl->fh_array[i]) |
541 | filelayout_free_fh_array(fl); | 565 | goto out_err_free; |
542 | return -ENOMEM; | 566 | |
543 | } | 567 | p = xdr_inline_decode(&stream, 4); |
568 | if (unlikely(!p)) | ||
569 | goto out_err_free; | ||
544 | fl->fh_array[i]->size = be32_to_cpup(p++); | 570 | fl->fh_array[i]->size = be32_to_cpup(p++); |
545 | if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) { | 571 | if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) { |
546 | printk(KERN_ERR "Too big fh %d received %d\n", | 572 | printk(KERN_ERR "Too big fh %d received %d\n", |
547 | i, fl->fh_array[i]->size); | 573 | i, fl->fh_array[i]->size); |
548 | filelayout_free_fh_array(fl); | 574 | goto out_err_free; |
549 | return -EIO; | ||
550 | } | 575 | } |
576 | |||
577 | p = xdr_inline_decode(&stream, fl->fh_array[i]->size); | ||
578 | if (unlikely(!p)) | ||
579 | goto out_err_free; | ||
551 | memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size); | 580 | memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size); |
552 | p += XDR_QUADLEN(fl->fh_array[i]->size); | ||
553 | dprintk("DEBUG: %s: fh len %d\n", __func__, | 581 | dprintk("DEBUG: %s: fh len %d\n", __func__, |
554 | fl->fh_array[i]->size); | 582 | fl->fh_array[i]->size); |
555 | } | 583 | } |
556 | 584 | ||
585 | __free_page(scratch); | ||
557 | return 0; | 586 | return 0; |
587 | |||
588 | out_err_free: | ||
589 | filelayout_free_fh_array(fl); | ||
590 | out_err: | ||
591 | __free_page(scratch); | ||
592 | return -EIO; | ||
558 | } | 593 | } |
559 | 594 | ||
560 | static void | 595 | static void |