}
static DEFINE_RWLOCK(fib_hash_lock);
+static unsigned int fib_hash_genid;
#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
fz->fz_hashmask = new_hashmask;
fz->fz_divisor = new_divisor;
fn_rebuild_zone(fz, old_ht, old_divisor);
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fz_hash_free(old_ht, old_divisor);
table->fn_zones[i]->fz_next = fz;
}
table->fn_zones[z] = fz;
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
return fz;
}
err = fib_semantic_match(&f->fn_alias,
flp, res,
+ f->fn_key, fz->fz_mask,
fz->fz_order);
if (err <= 0)
goto out;
fa->fa_scope = r->rtm_scope;
state = fa->fa_state;
fa->fa_state &= ~FA_S_ACCESSED;
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fib_release_info(fi_drop);
fib_insert_node(fz, new_f);
list_add_tail(&new_fa->fa_list,
(fa ? &fa->fa_list : &f->fn_alias));
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
if (new_f)
hlist_del(&f->fn_hash);
kill_fn = 1;
}
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
if (fa->fa_state & FA_S_ACCESSED)
hlist_del(&f->fn_hash);
kill_f = 1;
}
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fn_free_alias(fa);
struct hlist_head *hash_head;
struct fib_node *fn;
struct fib_alias *fa;
+ loff_t pos;
+ unsigned int genid;
+ int valid;
};
static struct fib_alias *fib_get_first(struct seq_file *seq)
iter->hash_head = NULL;
iter->fn = NULL;
iter->fa = NULL;
+ iter->pos = 0;
+ iter->genid = fib_hash_genid;
+ iter->valid = 1;
for (iter->zone = table->fn_zone_list; iter->zone;
iter->zone = iter->zone->fz_next) {
}
}
out:
+ iter->pos++;
return fa;
}
static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
{
- struct fib_alias *fa = fib_get_first(seq);
+ struct fib_iter_state *iter = seq->private;
+ struct fib_alias *fa;
+
+ if (iter->valid && pos >= iter->pos && iter->genid == fib_hash_genid) {
+ fa = iter->fa;
+ pos -= iter->pos;
+ } else
+ fa = fib_get_first(seq);
if (fa)
while (pos && (fa = fib_get_next(seq)))