diff options
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 |
