RK3588 Android12 DMABUF内存泄漏问题分析

RK3588 Android12 DMABUF内存泄漏问题分析

什么是DMABUF

DMABUF是多媒体设备之间共享内存的一种特定buffer结构,不同设备可以通过DMABUF的fd进行跨进程共享内存,实现零拷贝提高性能,支持异步访问降低模块耦合度。

问题描述

RK3588机器在线视频播放长时间拷机出现系统重启,log里面可以看到dma-buf内存分配失败,最后导致系统重启。

[05-15 04:55:46][64021.496139][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 1
[05-15 04:55:46][64021.496144][ T6554] iep2_process_reg_fd:270: reg[044]: 00000401 failed
[05-15 04:55:46][64021.496149][ T6554] rk_vcodec: mpp_process_task_default:602: alloc_task failed.
[05-15 04:55:46][64021.496155][ T6554] rk_vcodec: mpp_wait_result_default:842: session 6553:531 pending list is empty!
[05-15 04:55:46][64021.496160][ T6554] rk_vcodec: mpp_msgs_wait:1549: session 531 wait result ret -5
[05-15 04:55:46][64021.499857][ T6554] mpp_dma_import_fd:198: dma_buf_get fd 16 failed(-22)
[05-15 04:55:46][64021.499870][ T6554] rk_vcodec: mpp_task_attach_fd:1696: can't import dma-buf 16
[05-15 04:55:46][64021.499876][ T6554] iep2_process_reg_fd:270: reg[044]: 00000410 failed
[05-15 04:55:46][64021.499881][ T6554] rk_vcodec: mpp_process_task_default:602: alloc_task failed.
[05-15 04:55:46][64021.499888][ T6554] rk_vcodec: mpp_wait_result_default:842: session 6553:531 pending list is empty!
[05-15 04:55:46][64021.499893][ T6554] rk_vcodec: mpp_msgs_wait:1549: session 531 wait result ret -5

结合log及现象看比较大可能是内存泄漏导致,于是按如下方法来确认并定位是哪里泄漏。

问题分析

/proc/rk_dmabuf/dev 这个节点里面会记录当前的dma的使用信息:

130|rk3588_s_evb7:/ # cat /proc/rk_dmabuf/dev                                                                                                                                                 
          DMABUF NAME             EXPORT                 SIZE:KiB AttachedDevices

ffffff8022507400 402-allocator@4. system-uncached        2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff8143313a00 402-allocator@4. system-uncached        2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff819883e200 474-c2@1.1-servi rockchipdrm              56 KiB fdc38100.rkvdec-core
ffffff819daddc00 402-allocator@4. system-uncached        2628 KiB display-subsystem fb000000.gpu
ffffff80364ec200 402-allocator@4. system-uncached        2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff819dac0400 402-allocator@4. system-uncached        2628 KiB fb000000.gpu display-subsystem fb000000.gpu
ffffff81032a1400 402-allocator@4. system-uncached        2628 KiB display-subsystem fb000000.gpu
ffffff8102c5a400 402-allocator@4. system-uncached        1260 KiB fdbb0000.iep fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff8102c59800 402-allocator@4. system-uncached        1260 KiB fdbb0000.iep fb000000.gpu fdc38100.rkvdec-core display-subsystem
ffffff81049b9000 402-allocator@4. system-uncached        1260 KiB fdbb0000.iep fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff800f84de00 402-allocator@4. system-uncached        1260 KiB fdc38100.rkvdec-core fb000000.gpu display-subsystem
ffffff800f84c400 402-allocator@4. system-uncached        1260 KiB fb000000.gpu fdc38100.rkvdec-core display-subsystem

每个1个小时(根据实际泄漏的速度可以适当增加减小)敲一下如下命令,保存当前dma-buf的信息
cat /proc/rk_dmabuf/dev > sdcard/time1.txt
一小时后
cat /proc/rk_dmabuf/dev > sdcard/time2.txt
然后使用比较工具对比看两个文件的差异,看是否有多出的dma-buf信息
0f76c02639cd468dae9e37d51815ff2a.png#pic_center
对比发现ffffff81c260aa00 359-allocator@4. system-uncached 1740 KiB display-subsystem 这个一直在增加,通过 /sys/kernel/debug/dma_buf/bufinfo 输出的 dmabuf 的 inode 信息, 可以检索到哪些进程持有该 dmbuf 的 fd:

rk3588_s_evb7:/ # cat /sys/kernel/debug/dma_buf/bufinfo                                                                                                                                       

Dma-buf Objects:
size            flags           mode            count           exp_name        ino   
01781760        00000002        00080007        00000004        system-uncached 00520340        359-allocator@4.0-s
        Attached Devices:
        display-subsystem
Total 1 devices attached
01781760        00000002        00080007        00000004        system-uncached 00520339        359-allocator@4.0-s
        Attached Devices:
        display-subsystem
Total 1 devices attached
01781760        00000002        00080007        00000004        system-uncached 00143207        359-allocator@4.0-s
        Attached Devices:
        display-subsystem
Total 1 devices attached

01290240        00000002        00080007        00000004        system-uncached 00177498        359-allocator@4.0-s
        Attached Devices:
        display-subsystem
Total 1 devices attached

上面是 cat /sys/kernel/debug/dma_buf/bufinfo 的输出, 520339是某个 dmabuf 的 inode 的 i_ino 成员, 下面是在 lsof 的输出中检索到的该 iino , 即对应的进程以 fd 持有对对应 dmabuf 的引用. 一个 dmabuf 可能被多个 进程 这样引用:

rk3588s_s:/ # lsof | grep 520339                                                                                                                                                              
c2@1.1-service   426 mediacodec  235u     0000                0,8       0t0     520339 /dmabuf:359-allocator@4.0-s
rk3588s_s:/ # 
rk3588s_s:/ # 
rk3588s_s:/ # lsof | grep 143207                                                                                                                                                              
c2@1.1-service   426 mediacodec  117u     0000                0,8       0t0     143207 /dmabuf:359-allocator@4.0-s
rk3588s_s:/ # 
rk3588s_s:/ # lsof | grep 177498                                                                                                                                                              
c2@1.1-service   426 mediacodec   89u     0000                0,8       0t0     177498 /dmabuf:359-allocator@4.0-s

通过上面命令可以看到这个dma-buf的持有者是进程号:426的mediacodec进程,通过ls /proc/426/fd 可以看到有多个dma-buf的fd没有释放,这样就可以确认是mediacodec内有dma-buf没有释放,存在泄漏的问题,再找对应的模块负责人进行具体分析定位。