aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Olsson <robert.olsson@its.uu.se>2005-06-28 18:00:39 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-28 18:00:39 -0400
commitf835e471b557c45d2e5701ea5215f6e739b4eb39 (patch)
tree7239cecebed887017c69da258104ca71d419cdec
parent2f85a42964dd43fed3a339701db046bee5a8b903 (diff)
[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>
-rw-r--r--net/ipv4/fib_trie.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 0671569ee6f0..b56e88edf1b3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
43 * 2 of the License, or (at your option) any later version. 43 * 2 of the License, or (at your option) any later version.
44 */ 44 */
45 45
46#define VERSION "0.323" 46#define VERSION "0.324"
47 47
48#include <linux/config.h> 48#include <linux/config.h>
49#include <asm/uaccess.h> 49#include <asm/uaccess.h>
@@ -341,8 +341,10 @@ static struct leaf *leaf_new(void)
341static struct leaf_info *leaf_info_new(int plen) 341static struct leaf_info *leaf_info_new(int plen)
342{ 342{
343 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); 343 struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
344 li->plen = plen; 344 if(li) {
345 INIT_LIST_HEAD(&li->falh); 345 li->plen = plen;
346 INIT_LIST_HEAD(&li->falh);
347 }
346 return li; 348 return li;
347} 349}
348 350
@@ -879,8 +881,8 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
879 return (struct node*) tn; 881 return (struct node*) tn;
880} 882}
881 883
882static struct list_head * 884static struct list_head *
883fib_insert_node(struct trie *t, u32 key, int plen) 885fib_insert_node(struct trie *t, int *err, u32 key, int plen)
884{ 886{
885 int pos, newpos; 887 int pos, newpos;
886 struct tnode *tp = NULL, *tn = NULL; 888 struct tnode *tp = NULL, *tn = NULL;
@@ -940,7 +942,6 @@ fib_insert_node(struct trie *t, u32 key, int plen)
940 if(tp && IS_LEAF(tp)) 942 if(tp && IS_LEAF(tp))
941 BUG(); 943 BUG();
942 944
943 t->revision++;
944 945
945 /* Case 1: n is a leaf. Compare prefixes */ 946 /* Case 1: n is a leaf. Compare prefixes */
946 947
@@ -949,8 +950,10 @@ fib_insert_node(struct trie *t, u32 key, int plen)
949 950
950 li = leaf_info_new(plen); 951 li = leaf_info_new(plen);
951 952
952 if(! li) 953 if(! li) {
953 BUG(); 954 *err = -ENOMEM;
955 goto err;
956 }
954 957
955 fa_head = &li->falh; 958 fa_head = &li->falh;
956 insert_leaf_info(&l->list, li); 959 insert_leaf_info(&l->list, li);
@@ -959,14 +962,19 @@ fib_insert_node(struct trie *t, u32 key, int plen)
959 t->size++; 962 t->size++;
960 l = leaf_new(); 963 l = leaf_new();
961 964
962 if(! l) 965 if(! l) {
963 BUG(); 966 *err = -ENOMEM;
967 goto err;
968 }
964 969
965 l->key = key; 970 l->key = key;
966 li = leaf_info_new(plen); 971 li = leaf_info_new(plen);
967 972
968 if(! li) 973 if(! li) {
969 BUG(); 974 tnode_free((struct tnode *) l);
975 *err = -ENOMEM;
976 goto err;
977 }
970 978
971 fa_head = &li->falh; 979 fa_head = &li->falh;
972 insert_leaf_info(&l->list, li); 980 insert_leaf_info(&l->list, li);
@@ -1003,9 +1011,14 @@ fib_insert_node(struct trie *t, u32 key, int plen)
1003 newpos = 0; 1011 newpos = 0;
1004 tn = tnode_new(key, newpos, 1); /* First tnode */ 1012 tn = tnode_new(key, newpos, 1); /* First tnode */
1005 } 1013 }
1006 if(!tn)
1007 trie_bug("tnode_pfx_new failed");
1008 1014
1015 if(!tn) {
1016 free_leaf_info(li);
1017 tnode_free((struct tnode *) l);
1018 *err = -ENOMEM;
1019 goto err;
1020 }
1021
1009 NODE_SET_PARENT(tn, tp); 1022 NODE_SET_PARENT(tn, tp);
1010 1023
1011 missbit=tkey_extract_bits(key, newpos, 1); 1024 missbit=tkey_extract_bits(key, newpos, 1);
@@ -1027,7 +1040,9 @@ fib_insert_node(struct trie *t, u32 key, int plen)
1027 } 1040 }
1028 /* Rebalance the trie */ 1041 /* Rebalance the trie */
1029 t->trie = trie_rebalance(t, tp); 1042 t->trie = trie_rebalance(t, tp);
1030done:; 1043done:
1044 t->revision++;
1045err:;
1031 return fa_head; 1046 return fa_head;
1032} 1047}
1033 1048
@@ -1156,8 +1171,12 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1156 * Insert new entry to the list. 1171 * Insert new entry to the list.
1157 */ 1172 */
1158 1173
1159 if(!fa_head) 1174 if(!fa_head) {
1160 fa_head = fib_insert_node(t, key, plen); 1175 fa_head = fib_insert_node(t, &err, key, plen);
1176 err = 0;
1177 if(err)
1178 goto out_free_new_fa;
1179 }
1161 1180
1162 write_lock_bh(&fib_lock); 1181 write_lock_bh(&fib_lock);
1163 1182
@@ -1170,6 +1189,9 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1170 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); 1189 rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
1171succeeded: 1190succeeded:
1172 return 0; 1191 return 0;
1192
1193out_free_new_fa:
1194 kmem_cache_free(fn_alias_kmem, new_fa);
1173out: 1195out:
1174 fib_release_info(fi); 1196 fib_release_info(fi);
1175err:; 1197err:;