--- net/ipv4/fib_trie.c +++ net/ipv4/fib_trie.c.rcu @@ -97,30 +97,22 @@ #define IS_LEAF(n) (n->parent & T_LEAF) struct node { - unsigned long parent; - t_key key; + unsigned long parent; + t_key key; }; struct leaf { - unsigned long parent; - t_key key; - /* - * Because we have at least one info per leaf, we embedd one here - * to save some space and speedup lookups (sharing cache line) - * Note : not inside a structure so that we dont have holes on 64bit - */ - int plen_iinfo; - struct list_head falh_iinfo; - - struct hlist_head list; - struct rcu_head rcu; + unsigned long parent; + t_key key; + struct hlist_head list; + struct rcu_head rcu; }; struct leaf_info { - struct hlist_node hlist; - int plen; - struct list_head falh; - struct rcu_head rcu; + struct hlist_node hlist; + struct rcu_head rcu; + int plen; + struct list_head falh; }; struct tnode { @@ -381,13 +373,11 @@ call_rcu(&tn->rcu, __tnode_free_rcu); } -static struct leaf *leaf_new(int plen) +static struct leaf *leaf_new(void) { struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL); if (l) { l->parent = T_LEAF; - l->plen_iinfo = plen; - INIT_LIST_HEAD(&l->falh_iinfo); INIT_HLIST_HEAD(&l->list); } return l; @@ -909,12 +899,7 @@ static inline struct list_head * get_fa_head(struct leaf *l, int plen) { - struct leaf_info *li; - - if (plen == l->plen_iinfo) - return &l->falh_iinfo; - - li = find_leaf_info(l, plen); + struct leaf_info *li = find_leaf_info(l, plen); if (!li) return NULL; @@ -1071,22 +1056,21 @@ goto done; } t->size++; - l = leaf_new(plen); + l = leaf_new(); if (!l) return NULL; l->key = key; -// li = leaf_info_new(plen); + li = leaf_info_new(plen); + + if (!li) { + tnode_free((struct tnode *) l); + return NULL; + } -// if (!li) { -// tnode_free((struct tnode *) l); -// return NULL; -// } - -// fa_head = &li->falh; -// insert_leaf_info(&l->list, li); - fa_head = &l->falh_iinfo; + fa_head = &li->falh; + insert_leaf_info(&l->list, li); if (t->trie && n == NULL) { /* Case 2: n is NULL, and will just insert a new leaf */ @@ -1116,7 +1100,7 @@ } if (!tn) { -// free_leaf_info(li); + free_leaf_info(li); tnode_free((struct tnode *) l); return NULL; } @@ -1640,7 +1624,7 @@ li = find_leaf_info(l, plen); list_del_rcu(&fa->fa_list); -// FIXME + if (list_empty(fa_head)) { hlist_del_rcu(&li->hlist); free_leaf_info(li); @@ -2382,11 +2366,10 @@ seq_indent(seq, iter->depth); seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val)); for (i = 32; i >= 0; i--) { -// struct leaf_info *li = get_fa_head(l, i); //find_leaf_info(l, i); - struct list_head *fa_head = get_fa_head(l, i); - if (fa_head) { + struct leaf_info *li = find_leaf_info(l, i); + if (li) { struct fib_alias *fa; - list_for_each_entry_rcu(fa, fa_head, fa_list) { + list_for_each_entry_rcu(fa, &li->falh, fa_list) { seq_indent(seq, iter->depth+1); seq_printf(seq, " /%d %s %s", i, rtn_scope(fa->fa_scope), @@ -2465,18 +2448,17 @@ return 0; for (i=32; i>=0; i--) { - //struct leaf_info *li = find_leaf_info(l, i); - struct list_head *fa_head = get_fa_head(l, i); + struct leaf_info *li = find_leaf_info(l, i); struct fib_alias *fa; __be32 mask, prefix; - if (!fa_head) + if (!li) continue; - mask = inet_make_mask(i); + mask = inet_make_mask(li->plen); prefix = htonl(l->key); - list_for_each_entry_rcu(fa, fa_head, fa_list) { + list_for_each_entry_rcu(fa, &li->falh, fa_list) { const struct fib_info *fi = fa->fa_info; unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);