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:
William Liu authored and Xiaojun Ji committed 2023-08-06 22:22:06 -05:00
1 parent d06ffd55fe
commit 26c4796240
1 file changed
+58 -89
+58 -89
View File
@@ -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);