Move resources allocated using unmanaged interface to managed devm interface

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

[Posted February 20, 2007 by corbet]

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/

http://himangi99.wordpress.com/2014/05/16/move-resources-allocated-using-unmanaged-interface-to-managed-devm-interface/

)

devm_kzalloc and kmalloc的更多相关文章

  1. Linux内核 kmalloc, kzalloc & devm_kzalloc 区别【转】

    本文转载自:https://blog.csdn.net/u014628531/article/details/50711409 首先,kzalloc()实现了kmalloc()+memset()的功能 ...

  2. Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

    转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...

  3. 函数 devm_kzalloc()【转】

    本文转载自:http://blog.csdn.net/jgw2008/article/details/52691568 函数 devm_kzalloc() 和kzalloc()一样都是内核内存分配函数 ...

  4. linux中的内存申请函数的区别 kmalloc, vmalloc

    kmalloc是返回连续内存的内存分配函数 vmalloc是返回较大内存空间的,不需要连续的内存分配函数.其速度较慢,并且不能在中断上下文调用.

  5. mm/kmalloc.c

    /* *  linux/mm/kmalloc.c * *  Copyright (C) 1991, 1992  Linus Torvalds & Roger Wolff. * *  Writt ...

  6. Memory Allocation API In Linux Kernel && Linux Userspace、kmalloc vmalloc Difference、Kernel Large Section Memory Allocation

    目录 . 内核态(ring0)内存申请和用户态(ring3)内存申请 . 内核态(ring0)内存申请:kmalloc/kfree.vmalloc/vfree . 用户态(ring3)内存申请:mal ...

  7. malloc与kmalloc

    在设备驱动程序中动态开辟内存,不是用malloc,而是kmalloc,或者用get_free_pages直接申请页.释放内存用的是kfree,或free_pages. 对于提供了MMU(存储管理器,辅 ...

  8. malloc,vmalloc与kmalloc,kfree与vfree的区别和联系

    kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续kmalloc能分配的大小有 ...

  9. kmalloc/kfree,vmalloc/vfree函数用法和区别

    http://blog.csdn.net/tigerjibo/article/details/6412881 kmalloc/kfree,vmalloc/vfree函数用法和区别 1.kmalloc ...

随机推荐

  1. 多个div独立控制其显示/隐藏

    今天要说一个神奇的html标签op,静态页下可以配合jquery分别控制每个层的显示/隐藏切换. 如果用动态中使用,用文章id做区分就可以了. <html> <head> &l ...

  2. Spring 3整合Quartz 2实现定时任务一:常规整合 (基于maven构建)

    最近工作中需要用到定时任务的功能,虽然Spring3也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整合更为专业的Quartz来实现定时任务功能. 首先,当然是添加依 ...

  3. 排名第一、第二的OCR软件

    排名第一.第二的OCR软件 第一:ABBYY FineReader      OCR世界排名第一,在俄罗斯获国际科技大奖奖超过卡巴斯基! 不仅仅只是文字识别,还能表格识别,版面还原,字体识别,文档结构 ...

  4. 合并多个python list以及合并多个 django QuerySet 的方法

    在用python或者django写一些小工具应用的时候,有可能会遇到合并多个list到一个 list 的情况.单纯从技术角度来说,处理起来没什么难度,能想到的办法很多,但我觉得有一个很简单而且效率比较 ...

  5. bzoj 1187: [HNOI2007]神奇游乐园 插头dp

    1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 668  Solved: 337[Submit][Statu ...

  6. [原博客] BZOJ 2725 : [Violet 6]故乡的梦

    这个题在bzoj上好像是个权限题,想做的可以去Vani的博客下载测试数据.这里有题面. 简单叙述一下题意:给你一个n个点.m条边的带权无向图,S点和T点,询问Q次删一条给定的边的S-T最短路. 其中  ...

  7. 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)

    Tree Cutting Problem Description Byteasar has a tree T with n vertices conveniently labeled with 1,2 ...

  8. POJ - 3264 Balanced Lineup 线段树解RMQ

    这个题目是一个典型的RMQ问题,给定一个整数序列,1~N,然后进行Q次询问,每次给定两个整数A,B,(1<=A<=B<=N),求给定的范围内,最大和最小值之差. 解法一:这个是最初的 ...

  9. 使用reuseport和recvmmsg优化UDP服务器

    http://skoo.me/system/2014/03/18/udp-server-performance/ http://www.helplib.net/s/linux.die/65_3223/ ...

  10. 使用SparseArray代替HashMap

    HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...