diff options
author | Sasha Levin <sasha.levin@oracle.com> | 2015-04-14 18:45:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 19:49:00 -0400 |
commit | 8325330b026509127d4541e0f511c0c10648c2d5 (patch) | |
tree | 1db659fbd241f7810c44cfd4e1db22887a04fb73 | |
parent | 26b02a1f9670862c51b3ff63a6128589866f5c71 (diff) |
mm: cma: release trigger
Provides a userspace interface to trigger a CMA release.
Usage:
echo [pages] > free
This would provide testing/fuzzing access to the CMA release paths.
[akpm@linux-foundation.org: coding-style fixes]
[mhocko@suse.cz: fix build]
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Acked-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Laura Abbott <lauraa@codeaurora.org>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/cma_debug.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/mm/cma_debug.c b/mm/cma_debug.c index f3baa413ab33..ae41faeed596 100644 --- a/mm/cma_debug.c +++ b/mm/cma_debug.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/list.h> | 10 | #include <linux/list.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/mm_types.h> | ||
13 | 14 | ||
14 | #include "cma.h" | 15 | #include "cma.h" |
15 | 16 | ||
@@ -39,6 +40,60 @@ static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem) | |||
39 | spin_unlock(&cma->mem_head_lock); | 40 | spin_unlock(&cma->mem_head_lock); |
40 | } | 41 | } |
41 | 42 | ||
43 | static struct cma_mem *cma_get_entry_from_list(struct cma *cma) | ||
44 | { | ||
45 | struct cma_mem *mem = NULL; | ||
46 | |||
47 | spin_lock(&cma->mem_head_lock); | ||
48 | if (!hlist_empty(&cma->mem_head)) { | ||
49 | mem = hlist_entry(cma->mem_head.first, struct cma_mem, node); | ||
50 | hlist_del_init(&mem->node); | ||
51 | } | ||
52 | spin_unlock(&cma->mem_head_lock); | ||
53 | |||
54 | return mem; | ||
55 | } | ||
56 | |||
57 | static int cma_free_mem(struct cma *cma, int count) | ||
58 | { | ||
59 | struct cma_mem *mem = NULL; | ||
60 | |||
61 | while (count) { | ||
62 | mem = cma_get_entry_from_list(cma); | ||
63 | if (mem == NULL) | ||
64 | return 0; | ||
65 | |||
66 | if (mem->n <= count) { | ||
67 | cma_release(cma, mem->p, mem->n); | ||
68 | count -= mem->n; | ||
69 | kfree(mem); | ||
70 | } else if (cma->order_per_bit == 0) { | ||
71 | cma_release(cma, mem->p, count); | ||
72 | mem->p += count; | ||
73 | mem->n -= count; | ||
74 | count = 0; | ||
75 | cma_add_to_cma_mem_list(cma, mem); | ||
76 | } else { | ||
77 | pr_debug("cma: cannot release partial block when order_per_bit != 0\n"); | ||
78 | cma_add_to_cma_mem_list(cma, mem); | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | |||
85 | } | ||
86 | |||
87 | static int cma_free_write(void *data, u64 val) | ||
88 | { | ||
89 | int pages = val; | ||
90 | struct cma *cma = data; | ||
91 | |||
92 | return cma_free_mem(cma, pages); | ||
93 | } | ||
94 | |||
95 | DEFINE_SIMPLE_ATTRIBUTE(cma_free_fops, NULL, cma_free_write, "%llu\n"); | ||
96 | |||
42 | static int cma_alloc_mem(struct cma *cma, int count) | 97 | static int cma_alloc_mem(struct cma *cma, int count) |
43 | { | 98 | { |
44 | struct cma_mem *mem; | 99 | struct cma_mem *mem; |
@@ -85,6 +140,9 @@ static void cma_debugfs_add_one(struct cma *cma, int idx) | |||
85 | debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma, | 140 | debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma, |
86 | &cma_alloc_fops); | 141 | &cma_alloc_fops); |
87 | 142 | ||
143 | debugfs_create_file("free", S_IWUSR, cma_debugfs_root, cma, | ||
144 | &cma_free_fops); | ||
145 | |||
88 | debugfs_create_file("base_pfn", S_IRUGO, tmp, | 146 | debugfs_create_file("base_pfn", S_IRUGO, tmp, |
89 | &cma->base_pfn, &cma_debugfs_fops); | 147 | &cma->base_pfn, &cma_debugfs_fops); |
90 | debugfs_create_file("count", S_IRUGO, tmp, | 148 | debugfs_create_file("count", S_IRUGO, tmp, |