1/* 2 * ko_adapt.c 3 * 4 * function for find symbols not exported 5 * 6 * Copyright (C) 2022 Huawei Technologies Co., Ltd. 7 * 8 * This software is licensed under the terms of the GNU General Public 9 * License version 2, as published by the Free Software Foundation, and 10 * may be copied, distributed, and modified under those terms. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17#include "ko_adapt.h" 18#include <linux/types.h> 19#include <linux/mm_types.h> 20#include <linux/stddef.h> 21#include <linux/cred.h> 22#include <linux/version.h> 23#if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) 24#include <linux/sched/task.h> 25#endif 26#include <linux/cpumask.h> 27#include <linux/syscalls.h> 28#include <linux/fs.h> 29#include "tc_ns_log.h" 30 31typedef const struct cred *(get_task_cred_func)(struct task_struct *); 32typedef void (kthread_bind_mask_func)(struct task_struct *, const struct cpumask *); 33typedef struct page *(alloc_pages_func)(gfp_t gfp_mask, unsigned int order); 34typedef struct workqueue_attrs *(alloc_workqueue_attrs_func)(gfp_t gfp_mask); 35typedef void (free_workqueue_attrs_func)(struct workqueue_attrs *attrs); 36 37const struct cred *koadpt_get_task_cred(struct task_struct *task) 38{ 39#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 40 return get_task_cred(task); 41#else 42 static get_task_cred_func *get_task_cred_pt = NULL; 43 44 if (!task) 45 return NULL; 46 47 if (!get_task_cred_pt) { 48 get_task_cred_pt = (get_task_cred_func *) 49 (uintptr_t)kallsyms_lookup_name("get_task_cred"); 50 if (IS_ERR_OR_NULL(get_task_cred_pt)) { 51 tloge("fail to find symbol get task cred\n"); 52 return NULL; 53 } 54 } 55 return get_task_cred_pt(task); 56#endif 57} 58 59void koadpt_kthread_bind_mask(struct task_struct *task, 60 const struct cpumask *mask) 61{ 62#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 63 (void)set_cpus_allowed_ptr(task, mask); 64#else 65 static kthread_bind_mask_func *kthread_bind_mask_pt = NULL; 66 67 if (!task || !mask) 68 return; 69 70 if (!kthread_bind_mask_pt) { 71 kthread_bind_mask_pt = (kthread_bind_mask_func *) 72 (uintptr_t)kallsyms_lookup_name("kthread_bind_mask"); 73 if (IS_ERR_OR_NULL(kthread_bind_mask_pt)) { 74 tloge("fail to find symbol kthread bind mask\n"); 75 return; 76 } 77 } 78 kthread_bind_mask_pt(task, mask); 79#endif 80} 81 82struct page *koadpt_alloc_pages(gfp_t gfp_mask, unsigned int order) 83{ 84#ifdef CONFIG_NUMA 85#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 86 return alloc_pages(gfp_mask, order); 87#else 88 static alloc_pages_func *alloc_pages_pt = NULL; 89 90 if (!alloc_pages_pt) { 91 alloc_pages_pt = (alloc_pages_func *) 92 (uintptr_t)kallsyms_lookup_name("alloc_pages_current"); 93 if (IS_ERR_OR_NULL(alloc_pages_pt)) { 94 tloge("fail to find symbol alloc pages current\n"); 95 return NULL; 96 } 97 } 98 return alloc_pages_pt(gfp_mask, order); 99#endif 100#else 101 return alloc_pages(gfp_mask, order); 102#endif 103} 104 105struct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask) 106{ 107#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 108 struct workqueue_attrs *attrs; 109 (void)gfp_mask; 110 111 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 112 if (!attrs) { 113 tloge("alloc workqueue attr fail\n"); 114 return NULL; 115 } 116 117 if (alloc_cpumask_var(&attrs->cpumask, GFP_KERNEL) == false) { 118 tloge("alloc cpumask var fail\n"); 119 kfree(attrs); 120 return NULL; 121 } 122 123 cpumask_copy(attrs->cpumask, cpu_possible_mask); 124 125 return attrs; 126#else 127 static alloc_workqueue_attrs_func *alloc_workqueue_attrs_pt = NULL; 128 129 if (!alloc_workqueue_attrs_pt) { 130 alloc_workqueue_attrs_pt = (alloc_workqueue_attrs_func *) 131 (uintptr_t)kallsyms_lookup_name("alloc_workqueue_attrs"); 132 if (IS_ERR_OR_NULL(alloc_workqueue_attrs_pt)) { 133 tloge("fail to find symbol alloc workqueue attrs\n"); 134 return NULL; 135 } 136 } 137 return alloc_workqueue_attrs_pt(gfp_mask); 138#endif 139} 140 141void koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs) 142{ 143#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 144 if (!attrs) 145 return; 146 147 free_cpumask_var(attrs->cpumask); 148 kfree(attrs); 149#else 150 static free_workqueue_attrs_func *free_workqueue_attrs_pt = NULL; 151 152 if (!attrs) 153 return; 154 155 if (!free_workqueue_attrs_pt) { 156 free_workqueue_attrs_pt = (free_workqueue_attrs_func *) 157 (uintptr_t)kallsyms_lookup_name("free_workqueue_attrs"); 158 if (IS_ERR_OR_NULL(free_workqueue_attrs_pt)) { 159 tloge("fail to find symbol free workqueue attrs\n"); 160 return; 161 } 162 } 163 free_workqueue_attrs_pt(attrs); 164#endif 165}