TL; DR:扫描活动超级块并删除对非脏块的引用,直到您根据需要回收了尽可能多的系统内存. (或者你最终用尽了对活动超级块的引用.)
How to write kernel code to dynamically shrink the fs page-cache,
to recover just enough space so that a subsequent call to dma_alloc_coherent() succeeds?
要回答这个问题,让我们看一下“drop_caches操作”在您的系统上将fs页面缓存从27GB减少到94MB的功能.
> echo 1>的/ proc / sys目录/ VM / drop_caches
所调用
drop_caches_sysctl_handler()
>反过来调用iterate_supers()和
将指针传递给函数drop_pagecache_sb().
接下来发生的事情是iterate_supers()扫描活动超级块,每次找到一个时,它调用drop_pagecache_sb(),向活动超级块传递一个引用.
该迭代过程继续,直到从fs页面高速缓存中释放对所有活动超级块的引用.这是一种非破坏性操作,只会释放完全未使用的块.脏对象将继续使用,直到写入磁盘并且不可用.如果先运行同步将它们刷新到磁盘,“drop_caches操作”往往会释放更多内存.
Since you are interested in running this process to reclaim a limited/known amount of memory i.e. what is soon going to be requested using dma_alloc_coherent(), you simply need to implement the above functionality with an additional check at the end of each iteration and abort the superblock scan immediately once the amount of free system memory crosses the desired level.
要记住以下几点,以进一步优化此过程:
>某些块设备是否优先于其他块设备?
您可能希望首先迭代您不关心的块设备的活动超级块.如果没有回收足够的内存,则扫描您希望保留在fs页面缓存中的块设备,除非绝对需要回收所需的内存. get_active_super()可能在这里有所帮助.
> iterate_supers_type()似乎很有趣
它允许一个迭代特定file_system_type的超级块
请注意,这是一个推测性解决方案,完全基于您已经观察到已经解决问题的Linux内核中现有代码的分析.一旦实现了上述方法,它将只允许您控制相同的操作,即仅尝试回收fs页面缓存内存,仅满足您的即时需求.