moto mmap fault driver:Optimize the code flow
Remove the kprobe & lookup symbol make sure the android oem data is the one previous saved Change-Id: I7f63dd8fe5033fc9e1bcbf6182122da9fe7e7e85 Signed-off-by: William Liu <a17671@motorola.com> Reviewed-on: https://gerrit.mot.com/2658819 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao <zhaoxp3@motorola.com> Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2676238 Reviewed-by: Huosheng Liao <liaohs@motorola.com>
This commit is contained in:
1 parent
d06ffd55fe
commit
26c4796240
1 file changed
+58
-89
@@ -12,123 +12,92 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/mm.h> // struct mm_struct, apply_to_page_range()
|
|
||||||
#include <linux/kallsyms.h> // kallsyms_lookup_name()
|
|
||||||
#include <linux/vmalloc.h> // vm_unmap_aliases()
|
|
||||||
#include <trace/hooks/mm.h>
|
#include <trace/hooks/mm.h>
|
||||||
#include <linux/kprobes.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/version.h>
|
|
||||||
|
|
||||||
typedef struct page *(*page_cache_get_page_funct_t)(struct address_space *mapping, pgoff_t offset, int fgp_flags, gfp_t gfp_mask);
|
|
||||||
static page_cache_get_page_funct_t page_cache_get_page_func;
|
|
||||||
typedef unsigned long (*kallsyms_lookup_name_func_t)(const char *name);
|
|
||||||
static kallsyms_lookup_name_func_t kallsyms_lookup_name_func;
|
|
||||||
static int max_ra_pages = 8;
|
static int max_ra_pages = 8;
|
||||||
module_param(max_ra_pages, int, S_IRUGO | S_IWUSR);
|
module_param(max_ra_pages, int, S_IRUGO | S_IWUSR);
|
||||||
MODULE_PARM_DESC(max_ra_pages, "Max read ahead pages");
|
MODULE_PARM_DESC(max_ra_pages, "Max read ahead pages");
|
||||||
static void __nocfi filemap_fault_get_page(void *p, struct vm_fault *vmf, struct page **page_out, bool *retry)
|
static void __nocfi filemap_fault_get_page(void *p, struct vm_fault *vmf, struct page **page_out, bool *retry)
|
||||||
{
|
{
|
||||||
struct file *file = vmf->vma->vm_file;
|
struct file *file = vmf->vma->vm_file;
|
||||||
pgoff_t offset = vmf->pgoff;
|
pgoff_t offset = vmf->pgoff;
|
||||||
struct page *page = NULL;
|
struct page *page = NULL;
|
||||||
struct file_ra_state *ra = NULL;
|
struct file_ra_state *ra = NULL;
|
||||||
struct address_space *mapping = NULL;
|
struct address_space *mapping = NULL;
|
||||||
unsigned int mmap_miss;
|
unsigned int mmap_miss;
|
||||||
unsigned int old_ra_pages = 0;
|
unsigned int old_ra_pages = 0;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ra = &file->f_ra;
|
ra = &file->f_ra;
|
||||||
if(!ra)
|
if(!ra)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mapping = file->f_mapping;
|
mapping = file->f_mapping;
|
||||||
if (page_cache_get_page_func)
|
page = find_get_page(mapping, offset);
|
||||||
page = page_cache_get_page_func(mapping, offset, 0, 0);
|
|
||||||
|
|
||||||
if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
|
if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
|
||||||
put_page(page);
|
put_page(page);
|
||||||
} else if (!page) {
|
} else if (!page) {
|
||||||
mmap_miss = READ_ONCE(ra->mmap_miss);
|
mmap_miss = READ_ONCE(ra->mmap_miss);
|
||||||
if ((vmf->vma->vm_flags & VM_RAND_READ) ||
|
if ((vmf->vma->vm_flags & VM_RAND_READ) ||
|
||||||
(!ra->ra_pages) ||
|
(!ra->ra_pages) ||
|
||||||
(vmf->vma->vm_flags & VM_SEQ_READ) ||
|
(vmf->vma->vm_flags & VM_SEQ_READ) ||
|
||||||
mmap_miss > 100) {
|
mmap_miss > 100) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
old_ra_pages = ra->ra_pages;
|
old_ra_pages = ra->ra_pages;
|
||||||
if (ra->ra_pages > max_ra_pages) {
|
if (ra->ra_pages > max_ra_pages) {
|
||||||
ra->ra_pages = max_ra_pages; // reduce the read ahead limit to 8 pages
|
ra->ra_pages = max_ra_pages; // reduce the read ahead limit to 8 pages
|
||||||
vmf->android_oem_data1[0] = old_ra_pages;
|
vmf->android_oem_data1[0] = old_ra_pages;
|
||||||
vmf->android_oem_data1[1] = max_ra_pages;
|
vmf->android_oem_data1[1] = max_ra_pages;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
put_page(page);
|
put_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __nocfi filemap_fault_cache_page(void *p, struct vm_fault *vmf, struct page *page)
|
static void __nocfi filemap_fault_cache_page(void *p, struct vm_fault *vmf, struct page *page)
|
||||||
{
|
{
|
||||||
struct file *file = vmf->vma->vm_file;
|
struct file *file = vmf->vma->vm_file;
|
||||||
struct file_ra_state *ra = NULL;
|
struct file_ra_state *ra = NULL;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ra = &file->f_ra;
|
ra = &file->f_ra;
|
||||||
if(!ra)
|
if(!ra)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((ra->ra_pages == max_ra_pages) && (vmf->android_oem_data1[0] != 0) && (vmf->android_oem_data1[1] != 0)) {
|
if ((ra->ra_pages == max_ra_pages) && (vmf->android_oem_data1[0] != 0)
|
||||||
ra->ra_pages = (unsigned long)vmf->android_oem_data1[0]; //restore the old ra_pages
|
&& (vmf->android_oem_data1[1] == max_ra_pages)) {
|
||||||
vmf->android_oem_data1[0] = 0;
|
ra->ra_pages = (unsigned long)vmf->android_oem_data1[0]; //restore the old ra_pages
|
||||||
vmf->android_oem_data1[1] = 0;
|
vmf->android_oem_data1[0] = 0;
|
||||||
}
|
vmf->android_oem_data1[1] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __nocfi __init moto_mmap_fault_init(void)
|
static int __nocfi __init moto_mmap_fault_init(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct kprobe kp = {
|
ret = register_trace_android_vh_filemap_fault_get_page(filemap_fault_get_page, NULL) ?:
|
||||||
.symbol_name = "kallsyms_lookup_name",
|
register_trace_android_vh_filemap_fault_cache_page(filemap_fault_cache_page, NULL);
|
||||||
};
|
|
||||||
|
|
||||||
ret = register_kprobe(&kp);
|
if (ret != 0)
|
||||||
if (ret < 0) {
|
return -ENXIO;
|
||||||
pr_err("Failed to register kprobe, %d\n", ret);
|
else
|
||||||
return ret;
|
return 0;
|
||||||
}
|
|
||||||
unregister_kprobe(&kp);
|
|
||||||
kallsyms_lookup_name_func = (kallsyms_lookup_name_func_t)kp.addr;
|
|
||||||
if (!kallsyms_lookup_name_func) {
|
|
||||||
pr_err("Failed to get kallsyms_lookup_name address\n");
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
page_cache_get_page_func = (void *)kallsyms_lookup_name_func("pagecache_get_page");
|
|
||||||
if (!page_cache_get_page_func) {
|
|
||||||
pr_err("Failed to get required function\n");
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
ret = register_trace_android_vh_filemap_fault_get_page(filemap_fault_get_page, NULL) ?:
|
|
||||||
register_trace_android_vh_filemap_fault_cache_page(filemap_fault_cache_page, NULL);
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
return -ENXIO;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
static void __nocfi __exit moto_mmap_fault_exit(void)
|
static void __nocfi __exit moto_mmap_fault_exit(void)
|
||||||
{
|
{
|
||||||
unregister_trace_android_vh_filemap_fault_get_page(filemap_fault_get_page, NULL);
|
unregister_trace_android_vh_filemap_fault_get_page(filemap_fault_get_page, NULL);
|
||||||
unregister_trace_android_vh_filemap_fault_cache_page(filemap_fault_cache_page, NULL);
|
unregister_trace_android_vh_filemap_fault_cache_page(filemap_fault_cache_page, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(moto_mmap_fault_init);
|
module_init(moto_mmap_fault_init);
|
||||||
|
|||||||
Reference in new issue
Block a user