Move resources allocated using unmanaged interface to managed devm interface
转载:http://blog.csdn.net/swingboard/article/details/27207497
So today let’s talk about devm functions as that is what I have been upto the past couple of weeks. Yes, should have finished the task by now but due to some reasons was not active a couple of days :(.
Now what are devm functions. There are some common memory resources used
by drivers which are allocated using functions and stored as a linked
list of arbitrarily sized memory areas called devres. Some of this
memory is allocated in the probe function. But
all of this memory should be freed on a failure path or a driver
detach. Else, the driver will be leaking resources and wasting precious
main memory!
Detection of such memory leaks is difficult as they not clearly
noticeable. So, managed interfaces have been created for common
resources used by drivers. They have a name similar to the corresponding
unmanaged function making it easy to identify e.g.:
dma_alloc_coherent()
and dmam_alloc_coherent(), kzalloc() and devm_kzalloc(). If a managed
function is used for memory allocation the resources are guaranteed to
be freed both on initialization failure and driver detachment. Many of
these managed functions are devm functions.
eg: devm_kzalloc, devm_iio_device_alloc().
My task has been mainly to identify the cases where kzalloc() can be
changed to devm_kzalloc() and the corresponding kfree()s can be done
away with. Then the changes were applied and minor code changes like
removal of labels , removing of brackets in single
statement ifs were done. I have been using a Coccinelle semantic patch
to do this task and have made tweaks to handle some specific cases. Here
is a major part of the Coccinelle semantic patch making the change:
@platform@
identifier p, probefn, removefn;
@@
struct platform_driver p = {
.probe = probefn,
.remove = removefn,
};
@prb@
identifier platform.probefn, pdev;
expression e, e1, e2;
@@
probefn(struct platform_device *pdev, …) {
<+…
- e = kzalloc(e1, e2)
+ e = devm_kzalloc(&pdev->dev, e1, e2)
…
?-kfree(e);
…+>
}
@rem depends on prb@
identifier platform.removefn;
expression e;
@@
removefn(…) {
<…
- kfree(e);
…>
}
There are many cases in which a lot of code goes away and the probe
and remove functions appear really simple and easier to understand.
At the same time, there are issues such as cases to which the patch
applies but does not benefit much as there are major resources that are
still unmanaged. Also, some more advanced functions that can be managed
like IRQs have not been handled at this stage.
The managed resource API
The device resource managementpatch
was discussed here in January. That patch has now been mergedfor the
2.6.21 kernel. Since the API is now set - at least, as firmly asany
in-kernel API is - it
seems like a good time for a closer look at thisnew interface.
The core idea behind the resource management interface is that
remembering to freeallocated resources is hard. It appears to be
especially hard for driverwriters who, justly or not, have a reputation
for adding more than theirfair share of bugs to the kernel.
And even the best driver writers can runinto trouble in situations
where device probing fails halfway through; therecovery paths may be
there in the code, but they tend not to be welltested. The result of all
this is a fair number of resource leaks indriver
code.
To address this problem, Tejun Heo created a new set of resource
allocationfunctions which track allocations made by the driver. These
allocationsare associated with the
device structure; when the driver detachesfrom the device, any
left-over allocations are cleaned up. The resourcemanagement interface
is thus similar to the
talloc()API used by the Samba hackers, but it is adapted to the kernelenvironment and covers more than just memory allocations.
Starting with memory allocations, though, the new API is:
void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
void devm_kfree(struct device *dev, void *p);
In a pattern we'll see repeated below, the new functions are similar tokzalloc() and kfree() except for the new names and theaddition of the dev argument. That argument is necessary for theresource management code to know when the memory can be freed. If anymemory allocations are still outstanding when the associated device isremoved, they will all be freed at that time.
Note that there is no managed equivalent to kalloc(); if driverwriters cannot be trusted to free memory, it seems, they cannot be trustedto initialize it either. There are also no managed versions of thepage-level or slab allocation functions.
Managed versions of a subset of the DMA allocation functions have beenprovided:
void *dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
void *dmam_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size,
int flags);
void dmam_release_declared_memory(struct device *dev);
struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
size_t size, size_t align,
size_t allocation);
void dmam_pool_destroy(struct dma_pool *pool);
All of these functions have the same arguments and functionality as theirdma_* equivalents, but they will clean up the DMA areas on deviceshutdown. One still has to hope that the driver has ensuredthat no DMA remains active on those areas, or unpleasant things couldhappen.
There is a managed version of pci_enable_device():
int pcim_enable_device(struct pci_dev *pdev);
There is no pcim_disable_device(), however; code should just usepci_disable_device() as usual. A new function:
void pcim_pin_device(struct pci_dev *pdev);
will cause the given pdev to be left enabled even after the driverdetaches from it.
The patch makes the allocation of I/O memory regions withpci_request_region() managed by default - there is nopcim_ version of that interface. The higher-level allocation andmapping interfaces do have managed versions:
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar,
unsigned long maxlen);
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
For the allocation of interrupts, the managed API is:
int devm_request_irq(struct device *dev, unsigned int irq,
irq_handler_t handler, unsigned long irqflags,
const char *devname, void *dev_id);
void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
For these functions, the addition of a struct device argument wasrequired.
There is a new set of functions for the mapping of of I/O ports and memory:
void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
unsigned int nr);
void devm_ioport_unmap(struct device *dev, void __iomem *addr);
void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
unsigned long size);
void __iomem *devm_ioremap_nocache(struct device *dev,
unsigned long offset,
unsigned long size);
void devm_iounmap(struct device *dev, void __iomem *addr);
Once again, these functions required the addition of a structdevice argument for the managed form.
Finally, for those using the low-level resource allocation functions, themanaged versions are:
struct resource *devm_request_region(struct device *dev,
resource_size_t start,
resource_size_t n,
const char *name);
void devm_release_region(resource_size_t start, resource_size_t n);
struct resource *devm_request_mem_region(struct device *dev,
resource_size_t start,
resource_size_t n,
const char *name);
void devm_release_mem_region(resource_size_t start, resource_size_t n);
The resource management layer includes a "group" mechanism, accessed viathese functions:
void *devres_open_group(struct device *dev, void *id, gfp_t gfp);
void devres_close_group(struct device *dev, void *id);
void devres_remove_group(struct device *dev, void *id);
int devres_release_group(struct device *dev, void *id);
A group can be thought of as a marker in the list of allocations associatedwith a given device. Groups are created with devres_open_group(),which can be passed an id value to identify the group orNULL to have the ID generated on the fly; either way, theresulting group ID is returned. A call to devres_close_group()marks the end of a given group. Calling devres_remove_group()causes the system to forget about the given group, but does nothing withthe resources allocated within the group. To remove the group andimmediately free all resources allocated within that group,devres_release_group() should be used.
The group functions seem to be primarily aimed at mid-level code - the buslayers, for example. When bus code tries to attach a driver to a device,for example, it can open a group; should the driver attach fail, the groupcan be used to free up any resources allocated by the driver.
There are not many users of this new API in the kernel now. That maychange over time as driver writers become aware of these functions, and,perhaps, as the list of managed allocation types grows. The reward forswitching over to managed allocations should be more robust and simplercode as current failure and cleanup paths are removed.
(http://lwn.net/Articles/222860/
)
Move resources allocated using unmanaged interface to managed devm interface的更多相关文章
- xxx while the managed IDbConnection interface was being used: Login failed for user xxx
Process cube的时候遇到如下错误. Errors in the high-level relational engine. The following exception occurre ...
- 【Go入门教程6】interface(interface类型、interface值、空interface{}、嵌入interface、反射)
interface Go语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,当你看完这一章,你就会被interface的巧妙设计所折服. 什么是interface 简单 ...
- 【Go入门教程8】interface(interface类型、interface值、空interface{}、嵌入interface、反射)
interface Go语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,当你看完这一章,你就会被interface的巧妙设计所折服. 什么是interface 简单 ...
- 【转载】#437 - Access Interface Members through an Interface Variable
Onece a class implementation a particular interface, you can interact with the members of the interf ...
- JAVA的abstract修饰符 && 接口interface用法 && 抽象类和interface的差别
abstract修饰符可以修饰类和方法. (1)abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型(见后面实例),也就是编译时类型.抽象类就相当于 ...
- 一个Interface 继承多个Interface 的总结
我们知道在Java中的继承都是单继承的,就是说一个父类可以被多个子类继承但是一个子类只能有一个父类.但是一个接口可以被不同实现类去实现,这就是我们说的Java中的多态的概念.下面我们再来说一下接口的多 ...
- Single document interface和Multiple document interface
https://en.wikipedia.org/wiki/Single_document_interface https://msdn.microsoft.com/en-us/library/b2k ...
- devm_kzalloc and kmalloc
Move resources allocated using unmanaged interface to managed devm interface So today let's talk abo ...
- devm_xxx机制
前言 devm是内核提供的基础机制,用于方便驱动开发者所分配资源的自动回收.参考内核文档devres.txt.总的来说,就是驱动开发者只需要调用这类接口分配期望的资源,不用关心释放问题.这些资源的释放 ...
随机推荐
- cf965d Single-use Stones
ref #include <iostream> #include <cstdio> using namespace std; int a[100005], n, l, ans= ...
- leetcode 【 Convert Sorted List to Binary Search Tree 】python 实现
题目: Given a singly linked list where elements are sorted in ascending order, convert it to a height ...
- Github问题An error occurred trying to download
Github for windows安装过程出现了这样的问题An error occurred trying to download 'http://github-windows.s3.amazona ...
- Python+Selenium基础篇之5-第一个完整的自动化测试脚本
前面文章,我们介绍了如何采用XPath表达式去定位网页元素,在掌握了如何抓取或者如何书写精确的XPath表达式后,我们可以开始写自己的第一个真正意义上的webui 自动化测试脚本,就相当于,你在学习P ...
- LuffyCity-MySQL综合练习50实例
1.请创建如下表,并添加相应约束: 2.自行构造测试数据: 新建数据库 创建表 构造测试数据 #Step1-创建数据库LuffyCity_MySQL; #CREATE DATABASE LuffyCi ...
- 12小时制时间&&24小时制时间
今天在获取时间的时候发现,插入到数据库中的时间,其中下午的时间直接显示01,02的样子...查了下资料发现了端倪, java.text.SimpleDateFormat f=new java.text ...
- POJ1848 Tree 【树形dp】
题目链接 POJ1848 题解 由题,一个环至少由三个点组成,一个点作为根时,可以单独成链,可以与其一个儿子成链,或者与其两个儿子成环,与其一个剩余链长度大于等于2的儿子成环. 那么我们设最小代价 \ ...
- Angularjs的$apply及其优化使用
今天,我们要聊得是Angularjs中的小明星$apply.当我们数据更新了,但是view层却没反应时,总能听到有人说,用apply吧,然后,懵懂无知的我们,在赋值代码后面加了$scope.$appl ...
- Java众神之路(4)-关键字(下)
21.float float是Java原始类型. float变量可以存储单精度浮点值. 示例: float ratio = 0.1f; float diameter = 6.15f; 注释: 使用此关 ...
- 笔记:CS231n+assignment1(作业一)
CS231n的课后作业非常的好,这里记录一下自己对作业一些笔记. 一.第一个是KNN的代码,这里的trick是计算距离的三种方法,核心的话还是python和machine learning中非常实用的 ...