[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>
This commit is contained in:
Robert Olsson 2005-06-28 15:00:39 -07:00 committed by David S. Miller
parent 2f85a42964
commit f835e471b5

View File

@ -43,7 +43,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#define VERSION "0.323" #define VERSION "0.324"
#include <linux/config.h> #include <linux/config.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -341,8 +341,10 @@ static struct leaf *leaf_new(void)
static struct leaf_info *leaf_info_new(int plen) static struct leaf_info *leaf_info_new(int plen)
{ {
struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
li->plen = plen; if(li) {
INIT_LIST_HEAD(&li->falh); li->plen = plen;
INIT_LIST_HEAD(&li->falh);
}
return li; return li;
} }
@ -879,8 +881,8 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
return (struct node*) tn; return (struct node*) tn;
} }
static struct list_head * static struct list_head *
fib_insert_node(struct trie *t, u32 key, int plen) fib_insert_node(struct trie *t, int *err, u32 key, int plen)
{ {
int pos, newpos; int pos, newpos;
struct tnode *tp = NULL, *tn = NULL; struct tnode *tp = NULL, *tn = NULL;
@ -940,7 +942,6 @@ fib_insert_node(struct trie *t, u32 key, int plen)
if(tp && IS_LEAF(tp)) if(tp && IS_LEAF(tp))
BUG(); BUG();
t->revision++;
/* Case 1: n is a leaf. Compare prefixes */ /* Case 1: n is a leaf. Compare prefixes */
@ -949,8 +950,10 @@ fib_insert_node(struct trie *t, u32 key, int plen)
li = leaf_info_new(plen); li = leaf_info_new(plen);
if(! li) if(! li) {
BUG(); *err = -ENOMEM;
goto err;
}
fa_head = &li->falh; fa_head = &li->falh;
insert_leaf_info(&l->list, li); insert_leaf_info(&l->list, li);
@ -959,14 +962,19 @@ fib_insert_node(struct trie *t, u32 key, int plen)
t->size++; t->size++;
l = leaf_new(); l = leaf_new();
if(! l) if(! l) {
BUG(); *err = -ENOMEM;
goto err;
}
l->key = key; l->key = key;
li = leaf_info_new(plen); li = leaf_info_new(plen);
if(! li) if(! li) {
BUG(); tnode_free((struct tnode *) l);
*err = -ENOMEM;
goto err;
}
fa_head = &li->falh; fa_head = &li->falh;
insert_leaf_info(&l->list, li); insert_leaf_info(&l->list, li);
@ -1003,9 +1011,14 @@ fib_insert_node(struct trie *t, u32 key, int plen)
newpos = 0; newpos = 0;
tn = tnode_new(key, newpos, 1); /* First tnode */ tn = tnode_new(key, newpos, 1); /* First tnode */
} }
if(!tn)
trie_bug("tnode_pfx_new failed");
if(!tn) {
free_leaf_info(li);
tnode_free((struct tnode *) l);
*err = -ENOMEM;
goto err;
}
NODE_SET_PARENT(tn, tp); NODE_SET_PARENT(tn, tp);
missbit=tkey_extract_bits(key, newpos, 1); missbit=tkey_extract_bits(key, newpos, 1);
@ -1027,7 +1040,9 @@ fib_insert_node(struct trie *t, u32 key, int plen)
} }
/* Rebalance the trie */ /* Rebalance the trie */
t->trie = trie_rebalance(t, tp); t->trie = trie_rebalance(t, tp);
done:; done:
t->revision++;
err:;
return fa_head; return fa_head;
} }
@ -1156,8 +1171,12 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
* Insert new entry to the list. * Insert new entry to the list.
*/ */
if(!fa_head) if(!fa_head) {
fa_head = fib_insert_node(t, key, plen); fa_head = fib_insert_node(t, &err, key, plen);
err = 0;
if(err)
goto out_free_new_fa;
}
write_lock_bh(&fib_lock); write_lock_bh(&fib_lock);
@ -1170,6 +1189,9 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
succeeded: succeeded:
return 0; return 0;
out_free_new_fa:
kmem_cache_free(fn_alias_kmem, new_fa);
out: out:
fib_release_info(fi); fib_release_info(fi);
err:; err:;