diff options
Diffstat (limited to 'mm/util.c')
| -rw-r--r-- | mm/util.c | 70 |
1 files changed, 60 insertions, 10 deletions
| @@ -1,7 +1,9 @@ | |||
| 1 | #include <linux/mm.h> | ||
| 1 | #include <linux/slab.h> | 2 | #include <linux/slab.h> |
| 2 | #include <linux/string.h> | 3 | #include <linux/string.h> |
| 3 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 4 | #include <linux/err.h> | 5 | #include <linux/err.h> |
| 6 | #include <linux/sched.h> | ||
| 5 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 6 | 8 | ||
| 7 | /** | 9 | /** |
| @@ -68,25 +70,22 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) | |||
| 68 | EXPORT_SYMBOL(kmemdup); | 70 | EXPORT_SYMBOL(kmemdup); |
| 69 | 71 | ||
| 70 | /** | 72 | /** |
| 71 | * krealloc - reallocate memory. The contents will remain unchanged. | 73 | * __krealloc - like krealloc() but don't free @p. |
| 72 | * @p: object to reallocate memory for. | 74 | * @p: object to reallocate memory for. |
| 73 | * @new_size: how many bytes of memory are required. | 75 | * @new_size: how many bytes of memory are required. |
| 74 | * @flags: the type of memory to allocate. | 76 | * @flags: the type of memory to allocate. |
| 75 | * | 77 | * |
| 76 | * The contents of the object pointed to are preserved up to the | 78 | * This function is like krealloc() except it never frees the originally |
| 77 | * lesser of the new and old sizes. If @p is %NULL, krealloc() | 79 | * allocated buffer. Use this if you don't want to free the buffer immediately |
| 78 | * behaves exactly like kmalloc(). If @size is 0 and @p is not a | 80 | * like, for example, with RCU. |
| 79 | * %NULL pointer, the object pointed to is freed. | ||
| 80 | */ | 81 | */ |
| 81 | void *krealloc(const void *p, size_t new_size, gfp_t flags) | 82 | void *__krealloc(const void *p, size_t new_size, gfp_t flags) |
| 82 | { | 83 | { |
| 83 | void *ret; | 84 | void *ret; |
| 84 | size_t ks = 0; | 85 | size_t ks = 0; |
| 85 | 86 | ||
| 86 | if (unlikely(!new_size)) { | 87 | if (unlikely(!new_size)) |
| 87 | kfree(p); | ||
| 88 | return ZERO_SIZE_PTR; | 88 | return ZERO_SIZE_PTR; |
| 89 | } | ||
| 90 | 89 | ||
| 91 | if (p) | 90 | if (p) |
| 92 | ks = ksize(p); | 91 | ks = ksize(p); |
| @@ -95,10 +94,37 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags) | |||
| 95 | return (void *)p; | 94 | return (void *)p; |
| 96 | 95 | ||
| 97 | ret = kmalloc_track_caller(new_size, flags); | 96 | ret = kmalloc_track_caller(new_size, flags); |
| 98 | if (ret && p) { | 97 | if (ret && p) |
| 99 | memcpy(ret, p, ks); | 98 | memcpy(ret, p, ks); |
| 99 | |||
| 100 | return ret; | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL(__krealloc); | ||
| 103 | |||
| 104 | /** | ||
| 105 | * krealloc - reallocate memory. The contents will remain unchanged. | ||
| 106 | * @p: object to reallocate memory for. | ||
| 107 | * @new_size: how many bytes of memory are required. | ||
| 108 | * @flags: the type of memory to allocate. | ||
| 109 | * | ||
| 110 | * The contents of the object pointed to are preserved up to the | ||
| 111 | * lesser of the new and old sizes. If @p is %NULL, krealloc() | ||
| 112 | * behaves exactly like kmalloc(). If @size is 0 and @p is not a | ||
| 113 | * %NULL pointer, the object pointed to is freed. | ||
| 114 | */ | ||
| 115 | void *krealloc(const void *p, size_t new_size, gfp_t flags) | ||
| 116 | { | ||
| 117 | void *ret; | ||
| 118 | |||
| 119 | if (unlikely(!new_size)) { | ||
| 100 | kfree(p); | 120 | kfree(p); |
| 121 | return ZERO_SIZE_PTR; | ||
| 101 | } | 122 | } |
| 123 | |||
| 124 | ret = __krealloc(p, new_size, flags); | ||
| 125 | if (ret && p != ret) | ||
| 126 | kfree(p); | ||
| 127 | |||
| 102 | return ret; | 128 | return ret; |
| 103 | } | 129 | } |
| 104 | EXPORT_SYMBOL(krealloc); | 130 | EXPORT_SYMBOL(krealloc); |
| @@ -136,3 +162,27 @@ char *strndup_user(const char __user *s, long n) | |||
| 136 | return p; | 162 | return p; |
| 137 | } | 163 | } |
| 138 | EXPORT_SYMBOL(strndup_user); | 164 | EXPORT_SYMBOL(strndup_user); |
| 165 | |||
| 166 | #ifndef HAVE_ARCH_PICK_MMAP_LAYOUT | ||
| 167 | void arch_pick_mmap_layout(struct mm_struct *mm) | ||
| 168 | { | ||
| 169 | mm->mmap_base = TASK_UNMAPPED_BASE; | ||
| 170 | mm->get_unmapped_area = arch_get_unmapped_area; | ||
| 171 | mm->unmap_area = arch_unmap_area; | ||
| 172 | } | ||
| 173 | #endif | ||
| 174 | |||
| 175 | int __attribute__((weak)) get_user_pages_fast(unsigned long start, | ||
| 176 | int nr_pages, int write, struct page **pages) | ||
| 177 | { | ||
| 178 | struct mm_struct *mm = current->mm; | ||
| 179 | int ret; | ||
| 180 | |||
| 181 | down_read(&mm->mmap_sem); | ||
| 182 | ret = get_user_pages(current, mm, start, nr_pages, | ||
| 183 | write, 0, pages, NULL); | ||
| 184 | up_read(&mm->mmap_sem); | ||
| 185 | |||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | ||
