[英]kernel crash for spinlock concurrency in linux-kernel
I want to clear a list which type is defined by Kernel. 我想清除内核定义的类型列表。 I have two main structs, num_wrapper and num.
我有两个主要结构,num_wrapper和num。 num_wapper has a list of num, and kernel crashs when I do the del_all_node() function.
num_wapper有一个num列表,当我执行del_all_node()函数时,内核崩溃。
I try to mark the list_del, and the kernel will not be crash. 我尝试标记list_del,并且内核不会崩溃。 I don't understand why there will be crash problem since I have use spin_lock to protect this num_list.
我不明白为什么会有崩溃问题,因为我已经使用spin_lock保护了这个num_list。
Any tips will be appreciate. 任何提示将不胜感激。
The following is the simplified code. 以下是简化的代码。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
struct num_wrapper {
struct list_head num_list;
spinlock_t list_lock;
u8 check_num;
};
struct num {
struct list_head node;
int number;
struct num_wrapper* num_w_ptr;
};
s32 del_all_node(struct num_wrapper *number_wrap)
{
struct num *tmp;
struct num *num_head;
spin_lock(&number_wrap->list_lock);
list_for_each_entry_safe(num_head, tmp, &number_wrap->num_list, node) {
printk("num_head is %d\n", num_head->number);
list_del(&num_head->node);//this line seems to have problem
}
spin_unlock(&number_wrap->list_lock);
return 0;
}
static int __init hello_init(void)
{
/*Setup Scenario*/
struct num_wrapper *number_wrap = kzalloc(sizeof(struct num_wrapper)
, GFP_KERNEL);
struct num *number = kzalloc(sizeof(struct num), GFP_KERNEL);
number->number = 10;
number_wrap->check_num = 20;
INIT_LIST_HEAD(&number->node);
INIT_LIST_HEAD(&number_wrap->num_list);
list_add_tail(&number->node, &number_wrap->num_list);
del_all_node(number_wrap);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Good, haha\n");
}
module_init(hello_init);
module_exit(hello_exit);
update 更新
After doing some debug, I seems to find root cause... my scenario is as follows : 经过一些调试后,我似乎找到了根本原因...我的情况如下:
I have a private data struct which is included in the net_device struct. 我有一个私有数据结构,它包含在net_device结构中。 And the following is the simplified scenario:
以下是简化的场景:
struct xx_if *xx_if; //this is private data in net_device
struct xx_if *tmp;
list_for_each_entry_safe(xx_if, tmp, xx_if_wrap->if_list, list) {
free_netdev(xx_if->ndev);
list_del(&xx_if->list);
}
Since free_netdev will also free the private data xx_if, the code broken... My fix is change the sequence to these two statements, and it fix the crash problem. 由于free_netdev也将释放私有数据xx_if,因此代码已损坏...我的解决方法是将序列更改为这两个语句,并修复了崩溃问题。
Still strange thing is I have check whether xx_if is NULL, but still lead to crash if I don't interchange these two statements. 仍然很奇怪的是,我要检查xx_if是否为NULL,但是如果我不交换这两个语句,仍然会导致崩溃。
I don't clearly understand following code: 我不清楚以下代码:
INIT_LIST_HEAD(&number->node);
INIT_LIST_HEAD(&number_wrap->num_list);
list_add_tail(&number->node, &number_wrap->num_list);
You init two different structures, then you add one type of list to another type of list. 您初始化两个不同的结构,然后将一种类型的列表添加到另一种类型的列表中。
Is that the way you can do? 那是你可以做的方式吗?
I think, that you need something like this: 我认为您需要这样的东西:
struct num{
u8 check_num;
struct list_head list;
};
struct num_wrapper{
struct num* num_ptr;
spinlock_t list_lock;
};
int init_num_wrapper(struct num_wrapper** prt){
if(!ptr && *ptr){
return -EINVAL;
}
*ptr = kzalloc(sizeof(struct num_wrapper), GFP_KERNEL);
if(!*ptr){
return -ENOMEM;
}
INIT_LIST_HEAD(& (*ptr)->num_ptr->list);
... init spinlock
return 0;
}
int add_num(num_wrapper* prt_wrap, u8 check_num){
... checking pointers
struct num num* = NULL;
num = kmalloc(sizeof(struct num), GFP_KERNEL);
if(! num){
return -ENOMEM;
}
INIT_LIST_HEAD(&num->list);
num->check_num = check_num;
spin_lock(&prt_wrap->list_lock);
list_add_tail(&num->list, &prt_wrap->num_ptr.list);
spin_unlock(&prt_wrap->list_lock);
return 0;
}
int remove_all_nodes(num_wrapper* prt_wrap){
... checking pointer
struct num *tmp = NULL;
struct num *num_head = NULL;
spin_lock(&number_wrap->list_lock);
list_for_each_entry_safe(num_head, tmp, &prt_wrap->list, list)
{
printk("num_head is %d\n", num_head->number);
list_del(&num_head->node);//this line seems to have problem
}
spin_unlock(&num_wrapper->list_lock);
return 0;
}
Update 更新资料
Then, you can use above functions for manipulating of num_wrapper. 然后,您可以使用上述函数来操作num_wrapper。 For example:
例如:
//...
struct num_wrapper* nums = NULL;
init_num_wrapper(&nums); // after this call, you will have inited nums var, which can be used with others functions for manipulating with num_wrapper list.
u8 num = 2;
add_num(nums, num); // after this call new node with num will be added to num_wrapper
//...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.