diff options
author | Ilya Dryomov <ilya.dryomov@inktank.com> | 2014-03-13 10:36:15 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2014-04-05 00:07:44 -0400 |
commit | 86f1742b94dd0b4a2eb9255205d1756ddea182f8 (patch) | |
tree | 3ac1c58709b0aba00d2acb15ef17bc49ff630cf8 /net/ceph | |
parent | 9902e682c7f3df9ed5f60bc6f9c7efa6fd6b2d1d (diff) |
libceph: fixup error handling in osdmap_apply_incremental()
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. Follow osdmap_decode() and 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.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index d4a6b0df3627..b844a9273666 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -867,19 +867,19 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
867 | __s64 new_pool_max; | 867 | __s64 new_pool_max; |
868 | __s32 new_flags, max; | 868 | __s32 new_flags, max; |
869 | void *start = *p; | 869 | void *start = *p; |
870 | int err = -EINVAL; | 870 | int err; |
871 | u16 version; | 871 | u16 version; |
872 | 872 | ||
873 | dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p)); | 873 | dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p)); |
874 | 874 | ||
875 | ceph_decode_16_safe(p, end, version, bad); | 875 | ceph_decode_16_safe(p, end, version, e_inval); |
876 | if (version != 6) { | 876 | if (version != 6) { |
877 | pr_warning("got unknown v %d != 6 of inc osdmap\n", version); | 877 | pr_warning("got unknown v %d != 6 of inc osdmap\n", version); |
878 | goto bad; | 878 | goto e_inval; |
879 | } | 879 | } |
880 | 880 | ||
881 | ceph_decode_need(p, end, sizeof(fsid)+sizeof(modified)+2*sizeof(u32), | 881 | ceph_decode_need(p, end, sizeof(fsid)+sizeof(modified)+2*sizeof(u32), |
882 | bad); | 882 | e_inval); |
883 | ceph_decode_copy(p, &fsid, sizeof(fsid)); | 883 | ceph_decode_copy(p, &fsid, sizeof(fsid)); |
884 | epoch = ceph_decode_32(p); | 884 | epoch = ceph_decode_32(p); |
885 | BUG_ON(epoch != map->epoch+1); | 885 | BUG_ON(epoch != map->epoch+1); |
@@ -888,7 +888,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
888 | new_flags = ceph_decode_32(p); | 888 | new_flags = ceph_decode_32(p); |
889 | 889 | ||
890 | /* full map? */ | 890 | /* full map? */ |
891 | ceph_decode_32_safe(p, end, len, bad); | 891 | ceph_decode_32_safe(p, end, len, e_inval); |
892 | if (len > 0) { | 892 | if (len > 0) { |
893 | dout("apply_incremental full map len %d, %p to %p\n", | 893 | dout("apply_incremental full map len %d, %p to %p\n", |
894 | len, *p, end); | 894 | len, *p, end); |
@@ -896,13 +896,14 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
896 | } | 896 | } |
897 | 897 | ||
898 | /* new crush? */ | 898 | /* new crush? */ |
899 | ceph_decode_32_safe(p, end, len, bad); | 899 | ceph_decode_32_safe(p, end, len, e_inval); |
900 | if (len > 0) { | 900 | if (len > 0) { |
901 | dout("apply_incremental new crush map len %d, %p to %p\n", | ||
902 | len, *p, end); | ||
903 | newcrush = crush_decode(*p, min(*p+len, end)); | 901 | newcrush = crush_decode(*p, min(*p+len, end)); |
904 | if (IS_ERR(newcrush)) | 902 | if (IS_ERR(newcrush)) { |
905 | return ERR_CAST(newcrush); | 903 | err = PTR_ERR(newcrush); |
904 | newcrush = NULL; | ||
905 | goto bad; | ||
906 | } | ||
906 | *p += len; | 907 | *p += len; |
907 | } | 908 | } |
908 | 909 | ||
@@ -912,13 +913,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
912 | if (new_pool_max >= 0) | 913 | if (new_pool_max >= 0) |
913 | map->pool_max = new_pool_max; | 914 | map->pool_max = new_pool_max; |
914 | 915 | ||
915 | ceph_decode_need(p, end, 5*sizeof(u32), bad); | 916 | ceph_decode_need(p, end, 5*sizeof(u32), e_inval); |
916 | 917 | ||
917 | /* new max? */ | 918 | /* new max? */ |
918 | max = ceph_decode_32(p); | 919 | max = ceph_decode_32(p); |
919 | if (max >= 0) { | 920 | if (max >= 0) { |
920 | err = osdmap_set_max_osd(map, max); | 921 | err = osdmap_set_max_osd(map, max); |
921 | if (err < 0) | 922 | if (err) |
922 | goto bad; | 923 | goto bad; |
923 | } | 924 | } |
924 | 925 | ||
@@ -932,11 +933,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
932 | } | 933 | } |
933 | 934 | ||
934 | /* new_pool */ | 935 | /* new_pool */ |
935 | ceph_decode_32_safe(p, end, len, bad); | 936 | ceph_decode_32_safe(p, end, len, e_inval); |
936 | while (len--) { | 937 | while (len--) { |
937 | struct ceph_pg_pool_info *pi; | 938 | struct ceph_pg_pool_info *pi; |
938 | 939 | ||
939 | ceph_decode_64_safe(p, end, pool, bad); | 940 | ceph_decode_64_safe(p, end, pool, e_inval); |
940 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 941 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
941 | if (!pi) { | 942 | if (!pi) { |
942 | pi = kzalloc(sizeof(*pi), GFP_NOFS); | 943 | pi = kzalloc(sizeof(*pi), GFP_NOFS); |
@@ -953,29 +954,28 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
953 | } | 954 | } |
954 | if (version >= 5) { | 955 | if (version >= 5) { |
955 | err = __decode_pool_names(p, end, map); | 956 | err = __decode_pool_names(p, end, map); |
956 | if (err < 0) | 957 | if (err) |
957 | goto bad; | 958 | goto bad; |
958 | } | 959 | } |
959 | 960 | ||
960 | /* old_pool */ | 961 | /* old_pool */ |
961 | ceph_decode_32_safe(p, end, len, bad); | 962 | ceph_decode_32_safe(p, end, len, e_inval); |
962 | while (len--) { | 963 | while (len--) { |
963 | struct ceph_pg_pool_info *pi; | 964 | struct ceph_pg_pool_info *pi; |
964 | 965 | ||
965 | ceph_decode_64_safe(p, end, pool, bad); | 966 | ceph_decode_64_safe(p, end, pool, e_inval); |
966 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 967 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
967 | if (pi) | 968 | if (pi) |
968 | __remove_pg_pool(&map->pg_pools, pi); | 969 | __remove_pg_pool(&map->pg_pools, pi); |
969 | } | 970 | } |
970 | 971 | ||
971 | /* new_up */ | 972 | /* new_up */ |
972 | err = -EINVAL; | 973 | ceph_decode_32_safe(p, end, len, e_inval); |
973 | ceph_decode_32_safe(p, end, len, bad); | ||
974 | while (len--) { | 974 | while (len--) { |
975 | u32 osd; | 975 | u32 osd; |
976 | struct ceph_entity_addr addr; | 976 | struct ceph_entity_addr addr; |
977 | ceph_decode_32_safe(p, end, osd, bad); | 977 | ceph_decode_32_safe(p, end, osd, e_inval); |
978 | ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad); | 978 | ceph_decode_copy_safe(p, end, &addr, sizeof(addr), e_inval); |
979 | ceph_decode_addr(&addr); | 979 | ceph_decode_addr(&addr); |
980 | pr_info("osd%d up\n", osd); | 980 | pr_info("osd%d up\n", osd); |
981 | BUG_ON(osd >= map->max_osd); | 981 | BUG_ON(osd >= map->max_osd); |
@@ -984,11 +984,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
984 | } | 984 | } |
985 | 985 | ||
986 | /* new_state */ | 986 | /* new_state */ |
987 | ceph_decode_32_safe(p, end, len, bad); | 987 | ceph_decode_32_safe(p, end, len, e_inval); |
988 | while (len--) { | 988 | while (len--) { |
989 | u32 osd; | 989 | u32 osd; |
990 | u8 xorstate; | 990 | u8 xorstate; |
991 | ceph_decode_32_safe(p, end, osd, bad); | 991 | ceph_decode_32_safe(p, end, osd, e_inval); |
992 | xorstate = **(u8 **)p; | 992 | xorstate = **(u8 **)p; |
993 | (*p)++; /* clean flag */ | 993 | (*p)++; /* clean flag */ |
994 | if (xorstate == 0) | 994 | if (xorstate == 0) |
@@ -1000,10 +1000,10 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | /* new_weight */ | 1002 | /* new_weight */ |
1003 | ceph_decode_32_safe(p, end, len, bad); | 1003 | ceph_decode_32_safe(p, end, len, e_inval); |
1004 | while (len--) { | 1004 | while (len--) { |
1005 | u32 osd, off; | 1005 | u32 osd, off; |
1006 | ceph_decode_need(p, end, sizeof(u32)*2, bad); | 1006 | ceph_decode_need(p, end, sizeof(u32)*2, e_inval); |
1007 | osd = ceph_decode_32(p); | 1007 | osd = ceph_decode_32(p); |
1008 | off = ceph_decode_32(p); | 1008 | off = ceph_decode_32(p); |
1009 | pr_info("osd%d weight 0x%x %s\n", osd, off, | 1009 | pr_info("osd%d weight 0x%x %s\n", osd, off, |
@@ -1014,7 +1014,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | /* new_pg_temp */ | 1016 | /* new_pg_temp */ |
1017 | ceph_decode_32_safe(p, end, len, bad); | 1017 | ceph_decode_32_safe(p, end, len, e_inval); |
1018 | while (len--) { | 1018 | while (len--) { |
1019 | struct ceph_pg_mapping *pg; | 1019 | struct ceph_pg_mapping *pg; |
1020 | int j; | 1020 | int j; |
@@ -1024,22 +1024,22 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
1024 | err = ceph_decode_pgid(p, end, &pgid); | 1024 | err = ceph_decode_pgid(p, end, &pgid); |
1025 | if (err) | 1025 | if (err) |
1026 | goto bad; | 1026 | goto bad; |
1027 | ceph_decode_need(p, end, sizeof(u32), bad); | 1027 | ceph_decode_need(p, end, sizeof(u32), e_inval); |
1028 | pglen = ceph_decode_32(p); | 1028 | pglen = ceph_decode_32(p); |
1029 | if (pglen) { | 1029 | if (pglen) { |
1030 | ceph_decode_need(p, end, pglen*sizeof(u32), bad); | 1030 | ceph_decode_need(p, end, pglen*sizeof(u32), e_inval); |
1031 | 1031 | ||
1032 | /* removing existing (if any) */ | 1032 | /* removing existing (if any) */ |
1033 | (void) __remove_pg_mapping(&map->pg_temp, pgid); | 1033 | (void) __remove_pg_mapping(&map->pg_temp, pgid); |
1034 | 1034 | ||
1035 | /* insert */ | 1035 | /* insert */ |
1036 | err = -EINVAL; | ||
1037 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) | 1036 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) |
1038 | goto bad; | 1037 | goto e_inval; |
1039 | err = -ENOMEM; | ||
1040 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); | 1038 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); |
1041 | if (!pg) | 1039 | if (!pg) { |
1040 | err = -ENOMEM; | ||
1042 | goto bad; | 1041 | goto bad; |
1042 | } | ||
1043 | pg->pgid = pgid; | 1043 | pg->pgid = pgid; |
1044 | pg->len = pglen; | 1044 | pg->len = pglen; |
1045 | for (j = 0; j < pglen; j++) | 1045 | for (j = 0; j < pglen; j++) |
@@ -1063,6 +1063,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
1063 | dout("inc osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd); | 1063 | dout("inc osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd); |
1064 | return map; | 1064 | return map; |
1065 | 1065 | ||
1066 | e_inval: | ||
1067 | err = -EINVAL; | ||
1066 | bad: | 1068 | bad: |
1067 | pr_err("corrupt inc osdmap (%d) epoch %d off %d (%p of %p-%p)\n", | 1069 | pr_err("corrupt inc osdmap (%d) epoch %d off %d (%p of %p-%p)\n", |
1068 | err, epoch, (int)(*p - start), *p, start, end); | 1070 | err, epoch, (int)(*p - start), *p, start, end); |