您的位置:首页 > 理论基础 > 计算机网络

网络子系统39_inet_peer缓存通用接口

2013-10-05 16:32 579 查看
//	查找inet_peer
//	参数:
//		daddr,ip地址
//		create,指示daddr不存在时,是否新建

//	注:inet_peer在内存中组织为平衡树的形式
1.1 struct inet_peer *inet_getpeer(__be32 daddr, int create)
{
struct inet_peer *p, *n;
struct inet_peer **stack[PEER_MAXDEPTH], ***stackptr;

//获取读锁
read_lock_bh(&peer_pool_lock);
p = lookup(daddr, NULL);//执行查找
if (p != peer_avl_empty)//有效节点
atomic_inc(&p->refcnt);
read_unlock_bh(&peer_pool_lock);

if (p != peer_avl_empty) {
unlink_from_unused(p);//如果节点在unused_list链表上,从其上取下
return p;//返回
}

if (!create)//没有找到,并且不创建
return NULL;//返回空

//通过SLAB 分配一个inet_peer
n = kmem_cache_alloc(peer_cachep, GFP_ATOMIC);
if (n == NULL)
return NULL;
n->v4daddr = daddr;//ip地址
atomic_set(&n->refcnt, 1);//引用技术
atomic_set(&n->rid, 0);
n->ip_id_count = secure_ip_id(daddr);//随机生成一个ip id的起始值
n->tcp_ts_stamp = 0;

write_lock_bh(&peer_pool_lock);//获取写锁,
p = lookup(daddr, stack);//再一次查找,防止在之前的处理过程中,另一个并行路径,已经添加此inet_peer
if (p != peer_avl_empty)
goto out_free;//此地址被添加

link_to_pool(n);//将此节点连接到avl数中
INIT_LIST_HEAD(&n->unused);
peer_total++;//系统中inet_peer总数
write_unlock_bh(&peer_pool_lock);

if (peer_total >= inet_peer_threshold)
cleanup_once(0);//超过阀值,释放unused中第一个inet_peer

return n;

out_free:
atomic_inc(&p->refcnt);
write_unlock_bh(&peer_pool_lock);
unlink_from_unused(p);
kmem_cache_free(peer_cachep, n);
return p;
}

//	释放inet_peer引用计数
//	函数主要内容:
//		1.递减引用计数
//		2.如果引用计数=0,加入到unused_peers链表
//		3.更新inet_peer加入到unused_peers的时间戳

//	注:引用计数为0的inet_peer并不立即删除,而是挂载到unused_peers中, 由垃圾回收机制释放。
1.2 void inet_putpeer(struct inet_peer *p)
{
//在递减引用计数前,获取unused_list锁,防止先递减后被并发路径递增,使引用计数非0的inet_peer被加入到链表中
spin_lock_bh(&inet_peer_unused_lock);
if (atomic_dec_and_test(&p->refcnt)) {//如果引用计数为0,则将其加入到链表中
list_add_tail(&p->unused, &unused_peers);
p->dtime = (__u32)jiffies;//加入到链表的时间戳
}
spin_unlock_bh(&inet_peer_unused_lock);//开锁,开软中断
}

//	异步垃圾回收
//	函数主要任务:
//		1.根据系统中inet_peer数量,确定清理对象的范围
//		2.同步清理符合范围的inet_peer
//		3.根据清理的情况,调整下次异步垃圾回收的时间
//			3.1 如果系统中剩余inet_peer仍然超过阈值,则定时器下一次尽快到期
//			3.2 否则在一定范围内随机化下一次的到期时间
2.1 static void peer_check_expire(unsigned long dummy)
{
unsigned long now = jiffies;
int ttl;
//系统中inet_peer数量超过了阀值
if (peer_total >= inet_peer_threshold)
ttl = inet_peer_minttl;//确定未用时长的inet_peer作为清除对象
else
ttl = inet_peer_maxttl
- (inet_peer_maxttl - inet_peer_minttl) / HZ *
peer_total / inet_peer_threshold * HZ;
while (!cleanup_once(ttl)) {//清除老化的inter_peer
if (jiffies != now)//清除操作耗时超过了1个jiffies
break;
}

if (peer_total >= inet_peer_threshold)//数量仍然超过阀值
peer_periodic_timer.expires = jiffies + inet_peer_gc_mintime;//使gc尽快到期
else
peer_periodic_timer.expires = jiffies
+ inet_peer_gc_maxtime
- (inet_peer_gc_maxtime - inet_peer_gc_mintime) / HZ *
peer_total / inet_peer_threshold * HZ;
add_timer(&peer_periodic_timer);
}

//	同步垃圾回收
//		参数:
//			ttl, 回收inet_peer的标准,如果inet_peer->dtime > jiffies+ttl,则回收此inet_peer

//	调用路径:peer_check_expire->cleanup_once

//	注:
//		1.unused_list上的inet_peer仍然保存在avl树中,当inet_peer再次被使用时(inet_getpeer),会从unused_list
//		上取下,因此一个inet_peer会进出unused_list数次
//		2.进入unused_list的inet_peer,refcnt=0

//	函数主要任务:
//		1.遍历unused_list,取下满足条件的inet_peer
//		2.从avl树中删除此inet_peer
2.2 static int cleanup_once(unsigned long ttl)
{
struct inet_peer *p = NULL;

spin_lock_bh(&inet_peer_unused_lock);//关软中断,获取锁
if (!list_empty(&unused_peers)) {//存在未使用的inet_peer
__u32 delta;

p = list_first_entry(&unused_peers, struct inet_peer, unused);
delta = (__u32)jiffies - p->dtime;

if (delta < ttl) {//在unused_peers上度过的时间短于被清除的要求
spin_unlock_bh(&inet_peer_unused_lock);
return -1;//直接返回
}

list_del_init(&p->unused);//从unused链表上删除下来

atomic_inc(&p->refcnt);//增加引用技术,防止被其他系统释放
}
spin_unlock_bh(&inet_peer_unused_lock);

if (p == NULL)//没有空闲的inet_peer
return -1;

unlink_from_pool(p);//从avl树中删除inet_peer,调整avl树
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐