Blame view

mm/util.c 3.87 KB
16d69265b   Andrew Morton   uninline arch_pic...
1
  #include <linux/mm.h>
30992c97a   Matt Mackall   [PATCH] slob: int...
2
3
4
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/module.h>
96840aa00   Davi Arnaut   [PATCH] strndup_u...
5
  #include <linux/err.h>
3b8f14b41   Adrian Bunk   mm/util.c must #i...
6
  #include <linux/sched.h>
96840aa00   Davi Arnaut   [PATCH] strndup_u...
7
  #include <asm/uaccess.h>
30992c97a   Matt Mackall   [PATCH] slob: int...
8
9
  
  /**
30992c97a   Matt Mackall   [PATCH] slob: int...
10
   * kstrdup - allocate space for and copy an existing string
30992c97a   Matt Mackall   [PATCH] slob: int...
11
12
13
14
15
16
17
18
19
20
21
22
   * @s: the string to duplicate
   * @gfp: the GFP mask used in the kmalloc() call when allocating memory
   */
  char *kstrdup(const char *s, gfp_t gfp)
  {
  	size_t len;
  	char *buf;
  
  	if (!s)
  		return NULL;
  
  	len = strlen(s) + 1;
1d2c8eea6   Christoph Hellwig   [PATCH] slab: cle...
23
  	buf = kmalloc_track_caller(len, gfp);
30992c97a   Matt Mackall   [PATCH] slob: int...
24
25
26
27
28
  	if (buf)
  		memcpy(buf, s, len);
  	return buf;
  }
  EXPORT_SYMBOL(kstrdup);
96840aa00   Davi Arnaut   [PATCH] strndup_u...
29

1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
30
  /**
1e66df3ee   Jeremy Fitzhardinge   add kstrndup
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
   * kstrndup - allocate space for and copy an existing string
   * @s: the string to duplicate
   * @max: read at most @max chars from @s
   * @gfp: the GFP mask used in the kmalloc() call when allocating memory
   */
  char *kstrndup(const char *s, size_t max, gfp_t gfp)
  {
  	size_t len;
  	char *buf;
  
  	if (!s)
  		return NULL;
  
  	len = strnlen(s, max);
  	buf = kmalloc_track_caller(len+1, gfp);
  	if (buf) {
  		memcpy(buf, s, len);
  		buf[len] = '\0';
  	}
  	return buf;
  }
  EXPORT_SYMBOL(kstrndup);
  
  /**
1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
55
56
57
58
59
60
61
62
63
   * kmemdup - duplicate region of memory
   *
   * @src: memory region to duplicate
   * @len: memory region length
   * @gfp: GFP mask to use
   */
  void *kmemdup(const void *src, size_t len, gfp_t gfp)
  {
  	void *p;
1d2c8eea6   Christoph Hellwig   [PATCH] slab: cle...
64
  	p = kmalloc_track_caller(len, gfp);
1a2f67b45   Alexey Dobriyan   [PATCH] kmemdup: ...
65
66
67
68
69
  	if (p)
  		memcpy(p, src, len);
  	return p;
  }
  EXPORT_SYMBOL(kmemdup);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
70
  /**
93bc4e89c   Pekka Enberg   netfilter: fix do...
71
   * __krealloc - like krealloc() but don't free @p.
ef2ad80c7   Christoph Lameter   Slab allocators: ...
72
73
74
75
   * @p: object to reallocate memory for.
   * @new_size: how many bytes of memory are required.
   * @flags: the type of memory to allocate.
   *
93bc4e89c   Pekka Enberg   netfilter: fix do...
76
77
78
   * This function is like krealloc() except it never frees the originally
   * allocated buffer. Use this if you don't want to free the buffer immediately
   * like, for example, with RCU.
ef2ad80c7   Christoph Lameter   Slab allocators: ...
79
   */
93bc4e89c   Pekka Enberg   netfilter: fix do...
80
  void *__krealloc(const void *p, size_t new_size, gfp_t flags)
ef2ad80c7   Christoph Lameter   Slab allocators: ...
81
82
  {
  	void *ret;
ef8b4520b   Christoph Lameter   Slab allocators: ...
83
  	size_t ks = 0;
ef2ad80c7   Christoph Lameter   Slab allocators: ...
84

93bc4e89c   Pekka Enberg   netfilter: fix do...
85
  	if (unlikely(!new_size))
6cb8f9132   Christoph Lameter   Slab allocators: ...
86
  		return ZERO_SIZE_PTR;
ef2ad80c7   Christoph Lameter   Slab allocators: ...
87

ef8b4520b   Christoph Lameter   Slab allocators: ...
88
89
  	if (p)
  		ks = ksize(p);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
90
91
92
93
  	if (ks >= new_size)
  		return (void *)p;
  
  	ret = kmalloc_track_caller(new_size, flags);
93bc4e89c   Pekka Enberg   netfilter: fix do...
94
  	if (ret && p)
be21f0ab0   Adrian Bunk   fix mm/util.c:kre...
95
  		memcpy(ret, p, ks);
93bc4e89c   Pekka Enberg   netfilter: fix do...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  
  	return ret;
  }
  EXPORT_SYMBOL(__krealloc);
  
  /**
   * krealloc - reallocate memory. The contents will remain unchanged.
   * @p: object to reallocate memory for.
   * @new_size: how many bytes of memory are required.
   * @flags: the type of memory to allocate.
   *
   * The contents of the object pointed to are preserved up to the
   * lesser of the new and old sizes.  If @p is %NULL, krealloc()
   * behaves exactly like kmalloc().  If @size is 0 and @p is not a
   * %NULL pointer, the object pointed to is freed.
   */
  void *krealloc(const void *p, size_t new_size, gfp_t flags)
  {
  	void *ret;
  
  	if (unlikely(!new_size)) {
ef2ad80c7   Christoph Lameter   Slab allocators: ...
117
  		kfree(p);
93bc4e89c   Pekka Enberg   netfilter: fix do...
118
  		return ZERO_SIZE_PTR;
ef2ad80c7   Christoph Lameter   Slab allocators: ...
119
  	}
93bc4e89c   Pekka Enberg   netfilter: fix do...
120
121
122
123
  
  	ret = __krealloc(p, new_size, flags);
  	if (ret && p != ret)
  		kfree(p);
ef2ad80c7   Christoph Lameter   Slab allocators: ...
124
125
126
  	return ret;
  }
  EXPORT_SYMBOL(krealloc);
96840aa00   Davi Arnaut   [PATCH] strndup_u...
127
128
  /*
   * strndup_user - duplicate an existing string from user space
96840aa00   Davi Arnaut   [PATCH] strndup_u...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
   * @s: The string to duplicate
   * @n: Maximum number of bytes to copy, including the trailing NUL.
   */
  char *strndup_user(const char __user *s, long n)
  {
  	char *p;
  	long length;
  
  	length = strnlen_user(s, n);
  
  	if (!length)
  		return ERR_PTR(-EFAULT);
  
  	if (length > n)
  		return ERR_PTR(-EINVAL);
  
  	p = kmalloc(length, GFP_KERNEL);
  
  	if (!p)
  		return ERR_PTR(-ENOMEM);
  
  	if (copy_from_user(p, s, length)) {
  		kfree(p);
  		return ERR_PTR(-EFAULT);
  	}
  
  	p[length - 1] = '\0';
  
  	return p;
  }
  EXPORT_SYMBOL(strndup_user);
16d69265b   Andrew Morton   uninline arch_pic...
160
161
162
163
164
165
166
167
168
  
  #ifndef HAVE_ARCH_PICK_MMAP_LAYOUT
  void arch_pick_mmap_layout(struct mm_struct *mm)
  {
  	mm->mmap_base = TASK_UNMAPPED_BASE;
  	mm->get_unmapped_area = arch_get_unmapped_area;
  	mm->unmap_area = arch_unmap_area;
  }
  #endif
912985dce   Rusty Russell   mm: Make generic ...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  
  int __attribute__((weak)) get_user_pages_fast(unsigned long start,
  				int nr_pages, int write, struct page **pages)
  {
  	struct mm_struct *mm = current->mm;
  	int ret;
  
  	down_read(&mm->mmap_sem);
  	ret = get_user_pages(current, mm, start, nr_pages,
  					write, 0, pages, NULL);
  	up_read(&mm->mmap_sem);
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(get_user_pages_fast);