sharepool相关接口

本文将对sharepool相关接口进行总结

接口列表

接口名 功能 备注
sp_group_add_task 向sharepool中添加一个进程 不能用于中断上下文
sp_group_drop 丢弃一个spg 每次使用一个spg后调用

sp_group_add_task

函数声明

sp_group_add_task声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* sp_group_add_task() - Add a process to an share group (sp_group).
* @pid: the pid of the task to be added.
* @spg_id: the ID of the sp_group.
*
* A thread group can't be added to more than one sp_group.
*
* Return: A postive group number for success, -errno on failure.
*
* The manually specified ID is between [SPG_ID_MIN, SPG_ID_MAX].
* The automatically allocated ID is between [SPG_ID_AUTO_MIN, SPG_ID_AUTO_MAX].
* When negative, the return value is -errno.
*/
int sp_group_add_task(int pid, int spg_id)

流程图

向sharepool组中添加一个进程的整体流程图如下所示:

图片名称

spg id检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* mdc scene hack */
if (enable_mdc_default_group)
spg_id = mdc_default_group_id;

/* Valid spg id */
if ((spg_id < SPG_ID_MIN || spg_id > SPG_ID_AUTO)
&& spg_id != SPG_ID_DVPP_PASS_THROUGH) {
pr_err_ratelimited("share pool: task add group failed, invalid group id %d\n", spg_id);
return -EINVAL;
}

/* In auto spg range, find a usable spg. Here we just find and
* test the validation of the spg, we do not use it.
*/
if (spg_id >= SPG_ID_AUTO_MIN && spg_id <= SPG_ID_AUTO_MAX) {
spg = __sp_find_spg(pid, spg_id);

if (!spg) {
pr_err_ratelimited("share pool: spg %d hasn't been created\n", spg_id);
return -EINVAL;
}

down_read(&spg->rw_lock);
if (!spg_valid(spg)) {
up_read(&spg->rw_lock);
pr_err_ratelimited("share pool: task add group failed, group id %d is dead\n", spg_id);
sp_group_drop(spg);
return -EINVAL;
}
up_read(&spg->rw_lock);

/* We need to drop the spg, see __sp_find_spg, we regard finding
* of spg as an occupation action to spg
*/
sp_group_drop(spg);
}

/* Auto alloc a new spg between [SPG_ID_AUTO_MAX, SPG_ID_AUTO_MIN] */

if (spg_id == SPG_ID_AUTO) {
spg_id = ida_alloc_range(&sp_group_id_ida, SPG_ID_AUTO_MIN,
SPG_ID_AUTO_MAX, GFP_ATOMIC);
if (spg_id < 0) {
pr_err_ratelimited("share pool: task add group failed, auto generate group id failed\n");
return spg_id;
}
id_newly_generated = true;
}

/* DVPP type spg, we will discuss this later */
if (spg_id == SPG_ID_DVPP_PASS_THROUGH) {
spg_id = ida_alloc_range(&sp_group_id_ida,
SPG_ID_DVPP_PASS_THROUGH_MIN,
SPG_ID_DVPP_PASS_THROUGH_MAX, GFP_ATOMIC);
if (spg_id < 0) {
pr_err_ratelimited("share pool: task add group failed, DVPP auto generate group id failed\n");
return spg_id;
}
id_newly_generated = true;
}

寻找对应进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
down_write(&sp_group_sem);

rcu_read_lock(); // tash switch is not allowed

tsk = find_task_by_vpid(pid);
if (!tsk || (tsk->flags & PF_EXITING))
ret = -ESRCH;
else
get_task_struct(tsk);

rcu_read_unlock();
if (ret) {
up_write(&sp_group_sem);
free_new_spg_id(id_newly_generated, spg_id);
goto out;
}

寻找进程对应的mm

1
2
3
4
5
6
7
8
9
10
11
12
mm = get_task_mm(tsk->group_leader);
if (!mm) {
up_write(&sp_group_sem);
ret = -ESRCH;
free_new_spg_id(id_newly_generated, spg_id);
goto out_put_task;
} else if (mm->sp_group) { // The task has already joined a group
up_write(&sp_group_sem);
ret = -EEXIST;
free_new_spg_id(id_newly_generated, spg_id);
goto out_put_mm;
}

寻找或者分配一个spg

1
2
3
4
5
6
7
spg = find_or_alloc_sp_group(spg_id);
if (IS_ERR(spg)) {
up_write(&sp_group_sem);
ret = PTR_ERR(spg);
free_new_spg_id(id_newly_generated, spg_id);
goto out_put_mm;
}

更新spa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
list_for_each_entry(spa, &spg->spa_list, link) {
unsigned long populate = 0;
struct file *file = spa_file(spa);
unsigned long addr;

__sp_area_drop_locked(prev);
prev = spa;

atomic_inc(&spa->use_count);

if (spa->is_dead == true)
continue;

spin_unlock(&sp_area_lock);

if (spa->type == SPA_TYPE_K2SPG && spa->kva) {
addr = sp_remap_kva_to_vma(spa->kva, spa, mm);
if (IS_ERR_VALUE(addr))
pr_warn("share pool: task add group remap k2u failed, ret %ld\n", addr);

spin_lock(&sp_area_lock);
continue;
}

down_write(&mm->mmap_sem);
if (unlikely(mm->core_state)) {
sp_munmap_task_areas(mm, &spa->link);
up_write(&mm->mmap_sem);
ret = -EBUSY;
pr_err("share pool: task add group: encountered coredump, abort\n");
spin_lock(&sp_area_lock);
break;
}

addr = sp_mmap(mm, file, spa, &populate);
if (IS_ERR_VALUE(addr)) {
sp_munmap_task_areas(mm, &spa->link);
up_write(&mm->mmap_sem);
ret = addr;
pr_err("share pool: task add group sp mmap failed, ret %d\n", ret);
spin_lock(&sp_area_lock);
break;
}
up_write(&mm->mmap_sem);

if (populate) {
ret = do_mm_populate(mm, spa->va_start, populate, 0);
if (ret) {
if (unlikely(fatal_signal_pending(current)))
pr_warn_ratelimited("share pool: task add group failed, current thread is killed\n");
else
pr_warn_ratelimited("share pool: task add group failed, mm populate failed "
"(potential no enough memory when -12): %d, spa type is %d\n",
ret, spa->type);
down_write(&mm->mmap_sem);
sp_munmap_task_areas(mm, spa->link.next);
up_write(&mm->mmap_sem);
spin_lock(&sp_area_lock);
break;
}
}

spin_lock(&sp_area_lock);
}
0%