commit f52a4f4ea2c5ea3dc17561d32d839a3051e47b0c
Author: Julian Anastasov <[EMAIL PROTECTED]>
Date:   Fri Feb 15 01:38:53 2008 -0800

    IPV4: fib: fix route replacement, fib_info is shared
    
    Upstream commit: c18865f39276435abb9286f9a816cb5b66c99a00
    
    fib_info can be shared by many route prefixes but we don't want
    duplicate alternative routes for a prefix+tos+priority. Last change
    was not correct to check fib_treeref because it accounts usage from
    other prefixes. Additionally, avoid replacement without error if new
    route is same, as Joonwoo Park suggests.
    
    Signed-off-by: Julian Anastasov <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 0dfee27..2f78e1e 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -434,19 +434,43 @@ static int fn_hash_insert(struct fib_table *tb, struct 
fib_config *cfg)
 
        if (fa && fa->fa_tos == tos &&
            fa->fa_info->fib_priority == fi->fib_priority) {
-               struct fib_alias *fa_orig;
+               struct fib_alias *fa_first, *fa_match;
 
                err = -EEXIST;
                if (cfg->fc_nlflags & NLM_F_EXCL)
                        goto out;
 
+               /* We have 2 goals:
+                * 1. Find exact match for type, scope, fib_info to avoid
+                * duplicate routes
+                * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
+                */
+               fa_match = NULL;
+               fa_first = fa;
+               fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
+               list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
+                       if (fa->fa_tos != tos)
+                               break;
+                       if (fa->fa_info->fib_priority != fi->fib_priority)
+                               break;
+                       if (fa->fa_type == cfg->fc_type &&
+                           fa->fa_scope == cfg->fc_scope &&
+                           fa->fa_info == fi) {
+                               fa_match = fa;
+                               break;
+                       }
+               }
+
                if (cfg->fc_nlflags & NLM_F_REPLACE) {
                        struct fib_info *fi_drop;
                        u8 state;
 
-                       if (fi->fib_treeref > 1)
+                       fa = fa_first;
+                       if (fa_match) {
+                               if (fa == fa_match)
+                                       err = 0;
                                goto out;
-
+                       }
                        write_lock_bh(&fib_hash_lock);
                        fi_drop = fa->fa_info;
                        fa->fa_info = fi;
@@ -469,20 +493,11 @@ static int fn_hash_insert(struct fib_table *tb, struct 
fib_config *cfg)
                 * uses the same scope, type, and nexthop
                 * information.
                 */
-               fa_orig = fa;
-               fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-               list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
-                       if (fa->fa_tos != tos)
-                               break;
-                       if (fa->fa_info->fib_priority != fi->fib_priority)
-                               break;
-                       if (fa->fa_type == cfg->fc_type &&
-                           fa->fa_scope == cfg->fc_scope &&
-                           fa->fa_info == fi)
-                               goto out;
-               }
+               if (fa_match)
+                       goto out;
+
                if (!(cfg->fc_nlflags & NLM_F_APPEND))
-                       fa = fa_orig;
+                       fa = fa_first;
        }
 
        err = -ENOENT;
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to