]> Git Repo - J-linux.git/blob - lib/kunit/user_alloc.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / lib / kunit / user_alloc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * KUnit userspace memory allocation resource management.
4  */
5 #include <kunit/resource.h>
6 #include <kunit/test.h>
7 #include <linux/kthread.h>
8 #include <linux/mm.h>
9
10 struct kunit_vm_mmap_resource {
11         unsigned long addr;
12         size_t size;
13 };
14
15 /* vm_mmap() arguments */
16 struct kunit_vm_mmap_params {
17         struct file *file;
18         unsigned long addr;
19         unsigned long len;
20         unsigned long prot;
21         unsigned long flag;
22         unsigned long offset;
23 };
24
25 /* Create and attach a new mm if it doesn't already exist. */
26 static int kunit_attach_mm(void)
27 {
28         struct mm_struct *mm;
29
30         if (current->mm)
31                 return 0;
32
33         /* arch_pick_mmap_layout() is only sane with MMU systems. */
34         if (!IS_ENABLED(CONFIG_MMU))
35                 return -EINVAL;
36
37         mm = mm_alloc();
38         if (!mm)
39                 return -ENOMEM;
40
41         /* Define the task size. */
42         mm->task_size = TASK_SIZE;
43
44         /* Make sure we can allocate new VMAs. */
45         arch_pick_mmap_layout(mm, &current->signal->rlim[RLIMIT_STACK]);
46
47         /* Attach the mm. It will be cleaned up when the process dies. */
48         kthread_use_mm(mm);
49
50         return 0;
51 }
52
53 static int kunit_vm_mmap_init(struct kunit_resource *res, void *context)
54 {
55         struct kunit_vm_mmap_params *p = context;
56         struct kunit_vm_mmap_resource vres;
57         int ret;
58
59         ret = kunit_attach_mm();
60         if (ret)
61                 return ret;
62
63         vres.size = p->len;
64         vres.addr = vm_mmap(p->file, p->addr, p->len, p->prot, p->flag, p->offset);
65         if (!vres.addr)
66                 return -ENOMEM;
67         res->data = kmemdup(&vres, sizeof(vres), GFP_KERNEL);
68         if (!res->data) {
69                 vm_munmap(vres.addr, vres.size);
70                 return -ENOMEM;
71         }
72
73         return 0;
74 }
75
76 static void kunit_vm_mmap_free(struct kunit_resource *res)
77 {
78         struct kunit_vm_mmap_resource *vres = res->data;
79
80         /*
81          * Since this is executed from the test monitoring process,
82          * the test's mm has already been torn down. We don't need
83          * to run vm_munmap(vres->addr, vres->size), only clean up
84          * the vres.
85          */
86
87         kfree(vres);
88         res->data = NULL;
89 }
90
91 unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
92                             unsigned long addr, unsigned long len,
93                             unsigned long prot, unsigned long flag,
94                             unsigned long offset)
95 {
96         struct kunit_vm_mmap_params params = {
97                 .file = file,
98                 .addr = addr,
99                 .len = len,
100                 .prot = prot,
101                 .flag = flag,
102                 .offset = offset,
103         };
104         struct kunit_vm_mmap_resource *vres;
105
106         vres = kunit_alloc_resource(test,
107                                     kunit_vm_mmap_init,
108                                     kunit_vm_mmap_free,
109                                     GFP_KERNEL,
110                                     &params);
111         if (vres)
112                 return vres->addr;
113         return 0;
114 }
115 EXPORT_SYMBOL_GPL(kunit_vm_mmap);
116
117 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
This page took 0.032881 seconds and 4 git commands to generate.