diff options
author | Sasha Levin <sasha.levin@oracle.com> | 2015-04-14 18:44:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 19:49:00 -0400 |
commit | 26b02a1f9670862c51b3ff63a6128589866f5c71 (patch) | |
tree | a271f168640f4f89ceab15d354f2772f4e363091 | |
parent | 28b24c1fc8c22cabe5b8a16ffe6a61dfce51a1f2 (diff) |
mm: cma: allocation trigger
Provides a userspace interface to trigger a CMA allocation.
Usage:
echo [pages] > alloc
This would provide testing/fuzzing access to the CMA allocation paths.
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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | mm/cma.c | 6 | ||||
-rw-r--r-- | mm/cma.h | 4 | ||||
-rw-r--r-- | mm/cma_debug.c | 54 |
3 files changed, 63 insertions, 1 deletions
@@ -123,6 +123,12 @@ static int __init cma_activate_area(struct cma *cma) | |||
123 | } while (--i); | 123 | } while (--i); |
124 | 124 | ||
125 | mutex_init(&cma->lock); | 125 | mutex_init(&cma->lock); |
126 | |||
127 | #ifdef CONFIG_CMA_DEBUGFS | ||
128 | INIT_HLIST_HEAD(&cma->mem_head); | ||
129 | spin_lock_init(&cma->mem_head_lock); | ||
130 | #endif | ||
131 | |||
126 | return 0; | 132 | return 0; |
127 | 133 | ||
128 | err: | 134 | err: |
@@ -7,6 +7,10 @@ struct cma { | |||
7 | unsigned long *bitmap; | 7 | unsigned long *bitmap; |
8 | unsigned int order_per_bit; /* Order of pages represented by one bit */ | 8 | unsigned int order_per_bit; /* Order of pages represented by one bit */ |
9 | struct mutex lock; | 9 | struct mutex lock; |
10 | #ifdef CONFIG_CMA_DEBUGFS | ||
11 | struct hlist_head mem_head; | ||
12 | spinlock_t mem_head_lock; | ||
13 | #endif | ||
10 | }; | 14 | }; |
11 | 15 | ||
12 | extern struct cma cma_areas[MAX_CMA_AREAS]; | 16 | extern struct cma cma_areas[MAX_CMA_AREAS]; |
diff --git a/mm/cma_debug.c b/mm/cma_debug.c index 3af2de6d4e5f..f3baa413ab33 100644 --- a/mm/cma_debug.c +++ b/mm/cma_debug.c | |||
@@ -7,9 +7,18 @@ | |||
7 | 7 | ||
8 | #include <linux/debugfs.h> | 8 | #include <linux/debugfs.h> |
9 | #include <linux/cma.h> | 9 | #include <linux/cma.h> |
10 | #include <linux/list.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
10 | 13 | ||
11 | #include "cma.h" | 14 | #include "cma.h" |
12 | 15 | ||
16 | struct cma_mem { | ||
17 | struct hlist_node node; | ||
18 | struct page *p; | ||
19 | unsigned long n; | ||
20 | }; | ||
21 | |||
13 | static struct dentry *cma_debugfs_root; | 22 | static struct dentry *cma_debugfs_root; |
14 | 23 | ||
15 | static int cma_debugfs_get(void *data, u64 *val) | 24 | static int cma_debugfs_get(void *data, u64 *val) |
@@ -23,6 +32,46 @@ static int cma_debugfs_get(void *data, u64 *val) | |||
23 | 32 | ||
24 | DEFINE_SIMPLE_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu\n"); | 33 | DEFINE_SIMPLE_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu\n"); |
25 | 34 | ||
35 | static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem) | ||
36 | { | ||
37 | spin_lock(&cma->mem_head_lock); | ||
38 | hlist_add_head(&mem->node, &cma->mem_head); | ||
39 | spin_unlock(&cma->mem_head_lock); | ||
40 | } | ||
41 | |||
42 | static int cma_alloc_mem(struct cma *cma, int count) | ||
43 | { | ||
44 | struct cma_mem *mem; | ||
45 | struct page *p; | ||
46 | |||
47 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); | ||
48 | if (!mem) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | p = cma_alloc(cma, count, CONFIG_CMA_ALIGNMENT); | ||
52 | if (!p) { | ||
53 | kfree(mem); | ||
54 | return -ENOMEM; | ||
55 | } | ||
56 | |||
57 | mem->p = p; | ||
58 | mem->n = count; | ||
59 | |||
60 | cma_add_to_cma_mem_list(cma, mem); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int cma_alloc_write(void *data, u64 val) | ||
66 | { | ||
67 | int pages = val; | ||
68 | struct cma *cma = data; | ||
69 | |||
70 | return cma_alloc_mem(cma, pages); | ||
71 | } | ||
72 | |||
73 | DEFINE_SIMPLE_ATTRIBUTE(cma_alloc_fops, NULL, cma_alloc_write, "%llu\n"); | ||
74 | |||
26 | static void cma_debugfs_add_one(struct cma *cma, int idx) | 75 | static void cma_debugfs_add_one(struct cma *cma, int idx) |
27 | { | 76 | { |
28 | struct dentry *tmp; | 77 | struct dentry *tmp; |
@@ -33,12 +82,15 @@ static void cma_debugfs_add_one(struct cma *cma, int idx) | |||
33 | 82 | ||
34 | tmp = debugfs_create_dir(name, cma_debugfs_root); | 83 | tmp = debugfs_create_dir(name, cma_debugfs_root); |
35 | 84 | ||
85 | debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma, | ||
86 | &cma_alloc_fops); | ||
87 | |||
36 | debugfs_create_file("base_pfn", S_IRUGO, tmp, | 88 | debugfs_create_file("base_pfn", S_IRUGO, tmp, |
37 | &cma->base_pfn, &cma_debugfs_fops); | 89 | &cma->base_pfn, &cma_debugfs_fops); |
38 | debugfs_create_file("count", S_IRUGO, tmp, | 90 | debugfs_create_file("count", S_IRUGO, tmp, |
39 | &cma->count, &cma_debugfs_fops); | 91 | &cma->count, &cma_debugfs_fops); |
40 | debugfs_create_file("order_per_bit", S_IRUGO, tmp, | 92 | debugfs_create_file("order_per_bit", S_IRUGO, tmp, |
41 | &cma->order_per_bit, &cma_debugfs_fops); | 93 | &cma->order_per_bit, &cma_debugfs_fops); |
42 | 94 | ||
43 | u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32)); | 95 | u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32)); |
44 | debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s); | 96 | debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s); |