nf_conntrack_set_hashsize
本帖最后由 zhanglin496 于 2016-08-31 11:20 编辑int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
{
int i, bucket, vmalloced, old_vmalloced;
unsigned int hashsize, old_size;
struct hlist_nulls_head *hash, *old_hash;
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
if (current->nsproxy->net_ns != &init_net)
return -EOPNOTSUPP;
/* On boot, we can set this without any fancy locking. */
if (!nf_conntrack_htable_size)
return param_set_uint(val, kp);
hashsize = simple_strtoul(val, NULL, 0);
if (!hashsize)
return -EINVAL;
hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced, 1);
if (!hash)
return -ENOMEM;
/* Lookups in the old hash might happen in parallel, which means we
* might get false negatives during connection lookup. New connections
* created because of a false negative won't make it into the hash
* though since that required taking the lock.
*/
spin_lock_bh(&nf_conntrack_lock);
for (i = 0; i < init_net.ct.htable_size; i++) {
while (!hlist_nulls_empty(&init_net.ct.hash)) {
h = hlist_nulls_entry(init_net.ct.hash.first,
struct nf_conntrack_tuple_hash, hnnode);
ct = nf_ct_tuplehash_to_ctrack(h);
hlist_nulls_del_rcu(&h->hnnode);
bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct),
hashsize,
nf_conntrack_hash_rnd);
hlist_nulls_add_head_rcu(&h->hnnode, &hash);
}
}
old_size = init_net.ct.htable_size;
old_vmalloced = init_net.ct.hash_vmalloc;
old_hash = init_net.ct.hash;
init_net.ct.htable_size = nf_conntrack_htable_size = hashsize;
init_net.ct.hash_vmalloc = vmalloced;
init_net.ct.hash = hash;
spin_unlock_bh(&nf_conntrack_lock);
nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
return 0;
}
EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
&nf_conntrack_htable_size, 0600);
1、conntrack hash桶可以通过用户命令重新分配,我有个疑问,在老的hash表释放时,如何保证没有其他的路径在引用老的hash表,我看代码迁移完成后直接调用nf_ct_free_hashtable就把老的hash表给释放了,为什么没有调用rcu来同步呢?
2、CPU A调用nf_ct_free_hashtable释放老的hash表时,CPU B正在引用老的hash表,感觉会出问题啊?
3、感觉应该在调用nf_ct_free_hashtable时插入synchronize_rcu, 但实际上没有,why? 哈哈,好像是内核的BUG,在4.7.4 中修复了,我看了下4.0.5中也应该有这个问题
synchronize_net();
nf_ct_free_hashtable(old_hash, old_size);
return 0; 查看提交记录,在2016-05-05修复,同时patch也fix了另外一个bug,比如使用了新的hash表,却使用的旧的hash size,
我要是早点发现,说不定能给内核提交个patch,{:qq23:}
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5e3c61f981756361e7dc74e2c673121028449e35 的确有点震惊,赞楼上
页:
[1]