diff options
author | Robert Olsson <robert.olsson@its.uu.se> | 2005-06-28 18:00:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-28 18:00:39 -0400 |
commit | f835e471b557c45d2e5701ea5215f6e739b4eb39 (patch) | |
tree | 7239cecebed887017c69da258104ca71d419cdec | |
parent | 2f85a42964dd43fed3a339701db046bee5a8b903 (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.c | 56 |
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) | |||
341 | static struct leaf_info *leaf_info_new(int plen) | 341 | static 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 | ||
882 | static struct list_head * | 884 | static struct list_head * |
883 | fib_insert_node(struct trie *t, u32 key, int plen) | 885 | fib_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); |
1030 | done:; | 1043 | done: |
1044 | t->revision++; | ||
1045 | err:; | ||
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); |
1171 | succeeded: | 1190 | succeeded: |
1172 | return 0; | 1191 | return 0; |
1192 | |||
1193 | out_free_new_fa: | ||
1194 | kmem_cache_free(fn_alias_kmem, new_fa); | ||
1173 | out: | 1195 | out: |
1174 | fib_release_info(fi); | 1196 | fib_release_info(fi); |
1175 | err:; | 1197 | err:; |