radix_tree_insert
在Linux内核源代码中受spin_lock
保护。但是dmesg显示的警告信息如下:
[ 667.551326] dump_backtrace.cfi_jt+0x0/0x8
[ 667.556266] show_stack+0x1c/0x2c
[ 667.560415] dump_stack_lvl+0x94/0x100
[ 667.565017] ___might_sleep+0x194/0x1e4
[ 667.569688] __might_sleep+0x58/0x94
[ 667.574112] slab_pre_alloc_hook+0x5c/0xf0
[ 667.579066] kmem_cache_alloc+0x84/0x398
[ 667.583830] radix_tree_node_alloc+0x74/0x138
[ 667.589035] radix_tree_insert+0xf4/0x1fc
警告信息意味着radix_tree_insert
可能休眠,它不应该在原子上下文中。我还注意到radix_tree_insert
在某些代码中不受spin_lock
的保护。
radix_tree_insert需要spin_lock保护吗?我们需要关注警告信息吗?
和其他函数一样,修改一个根树,radix_tree_insert
应该在这些同步下调用,这(至少)防止其他修改并发地操作这在头文件include/linux/radix-tree.h中清楚地写了出来,它声明了基数树:
- 任何函数修改树或标签(插入或删除)项(设置或清除标签)必须排除其他修改,并且排除任何读取树的函数。
取决于特定的的使用场景这种同步可以是自旋锁、互斥锁或其他方式。
通常,特定基数树的同步机制在其声明附近描述。例如,fs/btrfs/ctree.h
中的声明如下:
/*
* radix tree that keeps track of delayed nodes of every inode,
* protected by inode_lock
*/
struct radix_tree_root delayed_nodes_tree;
一种用于修改的同步类型应该考虑gfp mask参数,该参数传递给基数树的构造函数并用于节点分配。也就是说,如果这个掩码参数是GFP_KERNEL,那么修改操作不应该在自旋锁下调用。