[IPV4]: Broken memory allocation in fib_trie

This should help up the insertion... but the resize is more crucial.
and complex and needs some thinking.

Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Robert Olsson and committed by David S. Miller f835e471 2f85a429

+39 -17
+39 -17
net/ipv4/fib_trie.c
··· 43 * 2 of the License, or (at your option) any later version. 44 */ 45 46 - #define VERSION "0.323" 47 48 #include <linux/config.h> 49 #include <asm/uaccess.h> ··· 341 static struct leaf_info *leaf_info_new(int plen) 342 { 343 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); 344 - li->plen = plen; 345 - INIT_LIST_HEAD(&li->falh); 346 return li; 347 } 348 ··· 881 return (struct node*) tn; 882 } 883 884 - static struct list_head * 885 - fib_insert_node(struct trie *t, u32 key, int plen) 886 { 887 int pos, newpos; 888 struct tnode *tp = NULL, *tn = NULL; ··· 942 if(tp && IS_LEAF(tp)) 943 BUG(); 944 945 - t->revision++; 946 947 /* Case 1: n is a leaf. Compare prefixes */ 948 ··· 950 951 li = leaf_info_new(plen); 952 953 - if(! li) 954 - BUG(); 955 956 fa_head = &li->falh; 957 insert_leaf_info(&l->list, li); ··· 962 t->size++; 963 l = leaf_new(); 964 965 - if(! l) 966 - BUG(); 967 968 l->key = key; 969 li = leaf_info_new(plen); 970 971 - if(! li) 972 - BUG(); 973 974 fa_head = &li->falh; 975 insert_leaf_info(&l->list, li); ··· 1011 newpos = 0; 1012 tn = tnode_new(key, newpos, 1); /* First tnode */ 1013 } 1014 - if(!tn) 1015 - trie_bug("tnode_pfx_new failed"); 1016 1017 NODE_SET_PARENT(tn, tp); 1018 1019 missbit=tkey_extract_bits(key, newpos, 1); ··· 1040 } 1041 /* Rebalance the trie */ 1042 t->trie = trie_rebalance(t, tp); 1043 - done:; 1044 return fa_head; 1045 } 1046 ··· 1171 * Insert new entry to the list. 1172 */ 1173 1174 - if(!fa_head) 1175 - fa_head = fib_insert_node(t, key, plen); 1176 1177 write_lock_bh(&fib_lock); 1178 ··· 1189 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); 1190 succeeded: 1191 return 0; 1192 out: 1193 fib_release_info(fi); 1194 err:;
··· 43 * 2 of the License, or (at your option) any later version. 44 */ 45 46 + #define VERSION "0.324" 47 48 #include <linux/config.h> 49 #include <asm/uaccess.h> ··· 341 static struct leaf_info *leaf_info_new(int plen) 342 { 343 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); 344 + if(li) { 345 + li->plen = plen; 346 + INIT_LIST_HEAD(&li->falh); 347 + } 348 return li; 349 } 350 ··· 879 return (struct node*) tn; 880 } 881 882 + static struct list_head * 883 + fib_insert_node(struct trie *t, int *err, u32 key, int plen) 884 { 885 int pos, newpos; 886 struct tnode *tp = NULL, *tn = NULL; ··· 940 if(tp && IS_LEAF(tp)) 941 BUG(); 942 943 944 /* Case 1: n is a leaf. Compare prefixes */ 945 ··· 949 950 li = leaf_info_new(plen); 951 952 + if(! li) { 953 + *err = -ENOMEM; 954 + goto err; 955 + } 956 957 fa_head = &li->falh; 958 insert_leaf_info(&l->list, li); ··· 959 t->size++; 960 l = leaf_new(); 961 962 + if(! l) { 963 + *err = -ENOMEM; 964 + goto err; 965 + } 966 967 l->key = key; 968 li = leaf_info_new(plen); 969 970 + if(! li) { 971 + tnode_free((struct tnode *) l); 972 + *err = -ENOMEM; 973 + goto err; 974 + } 975 976 fa_head = &li->falh; 977 insert_leaf_info(&l->list, li); ··· 1003 newpos = 0; 1004 tn = tnode_new(key, newpos, 1); /* First tnode */ 1005 } 1006 1007 + if(!tn) { 1008 + free_leaf_info(li); 1009 + tnode_free((struct tnode *) l); 1010 + *err = -ENOMEM; 1011 + goto err; 1012 + } 1013 + 1014 NODE_SET_PARENT(tn, tp); 1015 1016 missbit=tkey_extract_bits(key, newpos, 1); ··· 1027 } 1028 /* Rebalance the trie */ 1029 t->trie = trie_rebalance(t, tp); 1030 + done: 1031 + t->revision++; 1032 + err:; 1033 return fa_head; 1034 } 1035 ··· 1156 * Insert new entry to the list. 1157 */ 1158 1159 + if(!fa_head) { 1160 + fa_head = fib_insert_node(t, &err, key, plen); 1161 + err = 0; 1162 + if(err) 1163 + goto out_free_new_fa; 1164 + } 1165 1166 write_lock_bh(&fib_lock); 1167 ··· 1170 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); 1171 succeeded: 1172 return 0; 1173 + 1174 + out_free_new_fa: 1175 + kmem_cache_free(fn_alias_kmem, new_fa); 1176 out: 1177 fib_release_info(fi); 1178 err:;