aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-03-13 10:36:14 -0400
committerSage Weil <sage@inktank.com>2014-04-05 00:07:38 -0400
commit597b52f6ca247086371abd67e5083292a500e736 (patch)
tree15a2b0ca2d8a8f7ef8328d3803bba173d869aff0 /net/ceph
parenta2505d63ee0541d9b4685250b033192e68222e97 (diff)
libceph: fixup error handling in osdmap_decode()
The existing error handling scheme requires resetting err to -EINVAL prior to calling any ceph_decode_* macro. This is ugly and fragile, and there already are a few places where we would return 0 on error, due to a missing reset. Fix this by adding a special e_inval label to be used by all ceph_decode_* macros. Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Alex Elder <elder@linaro.org>
Diffstat (limited to 'net/ceph')
-rw-r--r--net/ceph/osdmap.c53
1 files changed, 27 insertions, 26 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index a82df6ea0749..298d076eee89 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -688,36 +688,37 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
688{ 688{
689 u16 version; 689 u16 version;
690 u32 len, max, i; 690 u32 len, max, i;
691 int err = -EINVAL;
692 u32 epoch = 0; 691 u32 epoch = 0;
693 void *start = *p; 692 void *start = *p;
693 int err;
694 struct ceph_pg_pool_info *pi; 694 struct ceph_pg_pool_info *pi;
695 695
696 dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p)); 696 dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p));
697 697
698 ceph_decode_16_safe(p, end, version, bad); 698 ceph_decode_16_safe(p, end, version, e_inval);
699 if (version > 6) { 699 if (version > 6) {
700 pr_warning("got unknown v %d > 6 of osdmap\n", version); 700 pr_warning("got unknown v %d > 6 of osdmap\n", version);
701 goto bad; 701 goto e_inval;
702 } 702 }
703 if (version < 6) { 703 if (version < 6) {
704 pr_warning("got old v %d < 6 of osdmap\n", version); 704 pr_warning("got old v %d < 6 of osdmap\n", version);
705 goto bad; 705 goto e_inval;
706 } 706 }
707 707
708 ceph_decode_need(p, end, 2*sizeof(u64)+6*sizeof(u32), bad); 708 ceph_decode_need(p, end, 2*sizeof(u64)+6*sizeof(u32), e_inval);
709 ceph_decode_copy(p, &map->fsid, sizeof(map->fsid)); 709 ceph_decode_copy(p, &map->fsid, sizeof(map->fsid));
710 epoch = map->epoch = ceph_decode_32(p); 710 epoch = map->epoch = ceph_decode_32(p);
711 ceph_decode_copy(p, &map->created, sizeof(map->created)); 711 ceph_decode_copy(p, &map->created, sizeof(map->created));
712 ceph_decode_copy(p, &map->modified, sizeof(map->modified)); 712 ceph_decode_copy(p, &map->modified, sizeof(map->modified));
713 713
714 ceph_decode_32_safe(p, end, max, bad); 714 ceph_decode_32_safe(p, end, max, e_inval);
715 while (max--) { 715 while (max--) {
716 ceph_decode_need(p, end, 8 + 2, bad); 716 ceph_decode_need(p, end, 8 + 2, e_inval);
717 err = -ENOMEM;
718 pi = kzalloc(sizeof(*pi), GFP_NOFS); 717 pi = kzalloc(sizeof(*pi), GFP_NOFS);
719 if (!pi) 718 if (!pi) {
719 err = -ENOMEM;
720 goto bad; 720 goto bad;
721 }
721 pi->id = ceph_decode_64(p); 722 pi->id = ceph_decode_64(p);
722 err = __decode_pool(p, end, pi); 723 err = __decode_pool(p, end, pi);
723 if (err < 0) { 724 if (err < 0) {
@@ -728,27 +729,25 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
728 } 729 }
729 730
730 err = __decode_pool_names(p, end, map); 731 err = __decode_pool_names(p, end, map);
731 if (err < 0) { 732 if (err)
732 dout("fail to decode pool names");
733 goto bad; 733 goto bad;
734 }
735 734
736 ceph_decode_32_safe(p, end, map->pool_max, bad); 735 ceph_decode_32_safe(p, end, map->pool_max, e_inval);
737 736
738 ceph_decode_32_safe(p, end, map->flags, bad); 737 ceph_decode_32_safe(p, end, map->flags, e_inval);
739 738
740 max = ceph_decode_32(p); 739 max = ceph_decode_32(p);
741 740
742 /* (re)alloc osd arrays */ 741 /* (re)alloc osd arrays */
743 err = osdmap_set_max_osd(map, max); 742 err = osdmap_set_max_osd(map, max);
744 if (err < 0) 743 if (err)
745 goto bad; 744 goto bad;
746 745
747 /* osds */ 746 /* osds */
748 err = -EINVAL;
749 ceph_decode_need(p, end, 3*sizeof(u32) + 747 ceph_decode_need(p, end, 3*sizeof(u32) +
750 map->max_osd*(1 + sizeof(*map->osd_weight) + 748 map->max_osd*(1 + sizeof(*map->osd_weight) +
751 sizeof(*map->osd_addr)), bad); 749 sizeof(*map->osd_addr)), e_inval);
750
752 *p += 4; /* skip length field (should match max) */ 751 *p += 4; /* skip length field (should match max) */
753 ceph_decode_copy(p, map->osd_state, map->max_osd); 752 ceph_decode_copy(p, map->osd_state, map->max_osd);
754 753
@@ -762,7 +761,7 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
762 ceph_decode_addr(&map->osd_addr[i]); 761 ceph_decode_addr(&map->osd_addr[i]);
763 762
764 /* pg_temp */ 763 /* pg_temp */
765 ceph_decode_32_safe(p, end, len, bad); 764 ceph_decode_32_safe(p, end, len, e_inval);
766 for (i = 0; i < len; i++) { 765 for (i = 0; i < len; i++) {
767 int n, j; 766 int n, j;
768 struct ceph_pg pgid; 767 struct ceph_pg pgid;
@@ -771,16 +770,16 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
771 err = ceph_decode_pgid(p, end, &pgid); 770 err = ceph_decode_pgid(p, end, &pgid);
772 if (err) 771 if (err)
773 goto bad; 772 goto bad;
774 ceph_decode_need(p, end, sizeof(u32), bad); 773 ceph_decode_need(p, end, sizeof(u32), e_inval);
775 n = ceph_decode_32(p); 774 n = ceph_decode_32(p);
776 err = -EINVAL;
777 if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) 775 if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
778 goto bad; 776 goto e_inval;
779 ceph_decode_need(p, end, n * sizeof(u32), bad); 777 ceph_decode_need(p, end, n * sizeof(u32), e_inval);
780 err = -ENOMEM;
781 pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); 778 pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS);
782 if (!pg) 779 if (!pg) {
780 err = -ENOMEM;
783 goto bad; 781 goto bad;
782 }
784 pg->pgid = pgid; 783 pg->pgid = pgid;
785 pg->len = n; 784 pg->len = n;
786 for (j = 0; j < n; j++) 785 for (j = 0; j < n; j++)
@@ -794,10 +793,10 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
794 } 793 }
795 794
796 /* crush */ 795 /* crush */
797 ceph_decode_32_safe(p, end, len, bad); 796 ceph_decode_32_safe(p, end, len, e_inval);
798 dout("osdmap_decode crush len %d from off 0x%x\n", len, 797 dout("osdmap_decode crush len %d from off 0x%x\n", len,
799 (int)(*p - start)); 798 (int)(*p - start));
800 ceph_decode_need(p, end, len, bad); 799 ceph_decode_need(p, end, len, e_inval);
801 map->crush = crush_decode(*p, end); 800 map->crush = crush_decode(*p, end);
802 *p += len; 801 *p += len;
803 if (IS_ERR(map->crush)) { 802 if (IS_ERR(map->crush)) {
@@ -812,6 +811,8 @@ static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map)
812 dout("full osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd); 811 dout("full osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd);
813 return 0; 812 return 0;
814 813
814e_inval:
815 err = -EINVAL;
815bad: 816bad:
816 pr_err("corrupt full osdmap (%d) epoch %d off %d (%p of %p-%p)\n", 817 pr_err("corrupt full osdmap (%d) epoch %d off %d (%p of %p-%p)\n",
817 err, epoch, (int)(*p - start), *p, start, end); 818 err, epoch, (int)(*p - start), *p, start, end);