Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] create a kstrdup library function

This patch creates a new kstrdup library function and changes the "local"
implementations in several places to use this function.

Most of the changes come from the sound and net subsystems. The sound part
had already been acknowledged by Takashi Iwai and the net part by David S.
Miller.

I left UML alone for now because I would need more time to read the code
carefully before making changes there.

Signed-off-by: Paulo Marques <pmarques@grupopie.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Paulo Marques and committed by
Linus Torvalds
543537bd 991114c6

+75 -94
+3 -11
drivers/md/dm-ioctl.c
··· 122 122 /*----------------------------------------------------------------- 123 123 * Inserting, removing and renaming a device. 124 124 *---------------------------------------------------------------*/ 125 - static inline char *kstrdup(const char *str) 126 - { 127 - char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); 128 - if (r) 129 - strcpy(r, str); 130 - return r; 131 - } 132 - 133 125 static struct hash_cell *alloc_cell(const char *name, const char *uuid, 134 126 struct mapped_device *md) 135 127 { ··· 131 139 if (!hc) 132 140 return NULL; 133 141 134 - hc->name = kstrdup(name); 142 + hc->name = kstrdup(name, GFP_KERNEL); 135 143 if (!hc->name) { 136 144 kfree(hc); 137 145 return NULL; ··· 141 149 hc->uuid = NULL; 142 150 143 151 else { 144 - hc->uuid = kstrdup(uuid); 152 + hc->uuid = kstrdup(uuid, GFP_KERNEL); 145 153 if (!hc->uuid) { 146 154 kfree(hc->name); 147 155 kfree(hc); ··· 265 273 /* 266 274 * duplicate new. 267 275 */ 268 - new_name = kstrdup(new); 276 + new_name = kstrdup(new, GFP_KERNEL); 269 277 if (!new_name) 270 278 return -ENOMEM; 271 279
+5 -13
drivers/parport/probe.c
··· 48 48 printk("\n"); 49 49 } 50 50 51 - static char *strdup(char *str) 52 - { 53 - int n = strlen(str)+1; 54 - char *s = kmalloc(n, GFP_KERNEL); 55 - if (!s) return NULL; 56 - return strcpy(s, str); 57 - } 58 - 59 51 static void parse_data(struct parport *port, int device, char *str) 60 52 { 61 53 char *txt = kmalloc(strlen(str)+1, GFP_KERNEL); ··· 80 88 if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { 81 89 if (info->mfr) 82 90 kfree (info->mfr); 83 - info->mfr = strdup(sep); 91 + info->mfr = kstrdup(sep, GFP_KERNEL); 84 92 } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { 85 93 if (info->model) 86 94 kfree (info->model); 87 - info->model = strdup(sep); 95 + info->model = kstrdup(sep, GFP_KERNEL); 88 96 } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { 89 97 int i; 90 98 if (info->class_name) 91 99 kfree (info->class_name); 92 - info->class_name = strdup(sep); 100 + info->class_name = kstrdup(sep, GFP_KERNEL); 93 101 for (u = sep; *u; u++) 94 102 *u = toupper(*u); 95 103 for (i = 0; classes[i].token; i++) { ··· 104 112 !strcmp(p, "COMMAND SET")) { 105 113 if (info->cmdset) 106 114 kfree (info->cmdset); 107 - info->cmdset = strdup(sep); 115 + info->cmdset = kstrdup(sep, GFP_KERNEL); 108 116 /* if it speaks printer language, it's 109 117 probably a printer */ 110 118 if (strstr(sep, "PJL") || strstr(sep, "PCL")) ··· 112 120 } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { 113 121 if (info->description) 114 122 kfree (info->description); 115 - info->description = strdup(sep); 123 + info->description = kstrdup(sep, GFP_KERNEL); 116 124 } 117 125 } 118 126 rock_on:
-4
include/linux/netdevice.h
··· 925 925 extern void net_enable_timestamp(void); 926 926 extern void net_disable_timestamp(void); 927 927 928 - #ifdef CONFIG_SYSCTL 929 - extern char *net_sysctl_strdup(const char *s); 930 - #endif 931 - 932 928 #endif /* __KERNEL__ */ 933 929 934 930 #endif /* _LINUX_DEV_H */
+2
include/linux/string.h
··· 88 88 extern void * memchr(const void *,int,__kernel_size_t); 89 89 #endif 90 90 91 + extern char *kstrdup(const char *s, int gfp); 92 + 91 93 #ifdef __cplusplus 92 94 } 93 95 #endif
+2 -1
include/sound/core.h
··· 292 292 void snd_hidden_kfree(const void *obj); 293 293 void *snd_hidden_vmalloc(unsigned long size); 294 294 void snd_hidden_vfree(void *obj); 295 + char *snd_hidden_kstrdup(const char *s, int flags); 295 296 #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) 296 297 #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) 297 298 #define kfree(obj) snd_hidden_kfree(obj) ··· 302 301 #define vmalloc_nocheck(size) snd_wrapper_vmalloc(size) 303 302 #define kfree_nocheck(obj) snd_wrapper_kfree(obj) 304 303 #define vfree_nocheck(obj) snd_wrapper_vfree(obj) 304 + #define kstrdup(s, flags) snd_hidden_kstrdup(s, flags) 305 305 #else 306 306 #define snd_memory_init() /*NOP*/ 307 307 #define snd_memory_done() /*NOP*/ ··· 313 311 #define kfree_nocheck(obj) kfree(obj) 314 312 #define vfree_nocheck(obj) vfree(obj) 315 313 #endif 316 - char *snd_kmalloc_strdup(const char *string, int flags); 317 314 int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count); 318 315 int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count); 319 316
+24
mm/slab.c
··· 92 92 #include <linux/sysctl.h> 93 93 #include <linux/module.h> 94 94 #include <linux/rcupdate.h> 95 + #include <linux/string.h> 95 96 96 97 #include <asm/uaccess.h> 97 98 #include <asm/cacheflush.h> ··· 3083 3082 3084 3083 return size; 3085 3084 } 3085 + 3086 + 3087 + /* 3088 + * kstrdup - allocate space for and copy an existing string 3089 + * 3090 + * @s: the string to duplicate 3091 + * @gfp: the GFP mask used in the kmalloc() call when allocating memory 3092 + */ 3093 + char *kstrdup(const char *s, int gfp) 3094 + { 3095 + size_t len; 3096 + char *buf; 3097 + 3098 + if (!s) 3099 + return NULL; 3100 + 3101 + len = strlen(s) + 1; 3102 + buf = kmalloc(len, gfp); 3103 + if (buf) 3104 + memcpy(buf, s, len); 3105 + return buf; 3106 + } 3107 + EXPORT_SYMBOL(kstrdup);
+2 -1
net/core/neighbour.c
··· 32 32 #include <net/sock.h> 33 33 #include <linux/rtnetlink.h> 34 34 #include <linux/random.h> 35 + #include <linux/string.h> 35 36 36 37 #define NEIGH_DEBUG 1 37 38 ··· 2593 2592 t->neigh_vars[17].extra1 = dev; 2594 2593 } 2595 2594 2596 - dev_name = net_sysctl_strdup(dev_name_source); 2595 + dev_name = kstrdup(dev_name_source, GFP_KERNEL); 2597 2596 if (!dev_name) { 2598 2597 err = -ENOBUFS; 2599 2598 goto free;
-15
net/core/sysctl_net_core.c
··· 35 35 extern char sysctl_divert_version[]; 36 36 #endif /* CONFIG_NET_DIVERT */ 37 37 38 - /* 39 - * This strdup() is used for creating copies of network 40 - * device names to be handed over to sysctl. 41 - */ 42 - 43 - char *net_sysctl_strdup(const char *s) 44 - { 45 - char *rv = kmalloc(strlen(s)+1, GFP_KERNEL); 46 - if (rv) 47 - strcpy(rv, s); 48 - return rv; 49 - } 50 - 51 38 ctl_table core_table[] = { 52 39 #ifdef CONFIG_NET 53 40 { ··· 163 176 }, 164 177 { .ctl_name = 0 } 165 178 }; 166 - 167 - EXPORT_SYMBOL(net_sysctl_strdup); 168 179 169 180 #endif
+1 -1
net/ipv4/devinet.c
··· 1471 1471 * by sysctl and we wouldn't want anyone to change it under our feet 1472 1472 * (see SIOCSIFNAME). 1473 1473 */ 1474 - dev_name = net_sysctl_strdup(dev_name); 1474 + dev_name = kstrdup(dev_name, GFP_KERNEL); 1475 1475 if (!dev_name) 1476 1476 goto free; 1477 1477
+2 -1
net/ipv6/addrconf.c
··· 57 57 #endif 58 58 #include <linux/delay.h> 59 59 #include <linux/notifier.h> 60 + #include <linux/string.h> 60 61 61 62 #include <net/sock.h> 62 63 #include <net/snmp.h> ··· 3438 3437 * by sysctl and we wouldn't want anyone to change it under our feet 3439 3438 * (see SIOCSIFNAME). 3440 3439 */ 3441 - dev_name = net_sysctl_strdup(dev_name); 3440 + dev_name = kstrdup(dev_name, GFP_KERNEL); 3442 3441 if (!dev_name) 3443 3442 goto free; 3444 3443
+2 -9
net/sunrpc/svcauth_unix.c
··· 8 8 #include <linux/err.h> 9 9 #include <linux/seq_file.h> 10 10 #include <linux/hash.h> 11 + #include <linux/string.h> 11 12 12 13 #define RPCDBG_FACILITY RPCDBG_AUTH 13 14 ··· 20 19 * AUTHNULL as for AUTHUNIX, and that is done here. 21 20 */ 22 21 23 - 24 - static char *strdup(char *s) 25 - { 26 - char *rv = kmalloc(strlen(s)+1, GFP_KERNEL); 27 - if (rv) 28 - strcpy(rv, s); 29 - return rv; 30 - } 31 22 32 23 struct unix_domain { 33 24 struct auth_domain h; ··· 48 55 if (new == NULL) 49 56 return NULL; 50 57 cache_init(&new->h.h); 51 - new->h.name = strdup(name); 58 + new->h.name = kstrdup(name, GFP_KERNEL); 52 59 new->h.flavour = RPC_AUTH_UNIX; 53 60 new->addr_changes = 0; 54 61 new->h.h.expiry_time = NEVER;
+2 -1
sound/core/info.c
··· 24 24 #include <linux/vmalloc.h> 25 25 #include <linux/time.h> 26 26 #include <linux/smp_lock.h> 27 + #include <linux/string.h> 27 28 #include <sound/core.h> 28 29 #include <sound/minors.h> 29 30 #include <sound/info.h> ··· 755 754 entry = kcalloc(1, sizeof(*entry), GFP_KERNEL); 756 755 if (entry == NULL) 757 756 return NULL; 758 - entry->name = snd_kmalloc_strdup(name, GFP_KERNEL); 757 + entry->name = kstrdup(name, GFP_KERNEL); 759 758 if (entry->name == NULL) { 760 759 kfree(entry); 761 760 return NULL;
+2 -1
sound/core/info_oss.c
··· 22 22 #include <sound/driver.h> 23 23 #include <linux/slab.h> 24 24 #include <linux/time.h> 25 + #include <linux/string.h> 25 26 #include <sound/core.h> 26 27 #include <sound/minors.h> 27 28 #include <sound/info.h> ··· 52 51 x = NULL; 53 52 } 54 53 } else { 55 - x = snd_kmalloc_strdup(string, GFP_KERNEL); 54 + x = kstrdup(string, GFP_KERNEL); 56 55 if (x == NULL) { 57 56 up(&strings); 58 57 return -ENOMEM;
+14 -27
sound/core/memory.c
··· 184 184 snd_wrapper_vfree(obj); 185 185 } 186 186 187 + char *snd_hidden_kstrdup(const char *s, int flags) 188 + { 189 + int len; 190 + char *buf; 191 + 192 + if (!s) return NULL; 193 + 194 + len = strlen(s) + 1; 195 + buf = _snd_kmalloc(len, flags); 196 + if (buf) 197 + memcpy(buf, s, len); 198 + return buf; 199 + } 200 + 187 201 static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) 188 202 { 189 203 snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); ··· 228 214 return 0; 229 215 } 230 216 231 - #else 232 - 233 - #define _snd_kmalloc kmalloc 234 - 235 217 #endif /* CONFIG_SND_DEBUG_MEMORY */ 236 - 237 - /** 238 - * snd_kmalloc_strdup - copy the string 239 - * @string: the original string 240 - * @flags: allocation conditions, GFP_XXX 241 - * 242 - * Allocates a memory chunk via kmalloc() and copies the string to it. 243 - * 244 - * Returns the pointer, or NULL if no enoguh memory. 245 - */ 246 - char *snd_kmalloc_strdup(const char *string, int flags) 247 - { 248 - size_t len; 249 - char *ptr; 250 - 251 - if (!string) 252 - return NULL; 253 - len = strlen(string) + 1; 254 - ptr = _snd_kmalloc(len, flags); 255 - if (ptr) 256 - memcpy(ptr, string, len); 257 - return ptr; 258 - } 259 218 260 219 /** 261 220 * copy_to_user_fromio - copy data from mmio-space to user-space
+2 -1
sound/core/oss/mixer_oss.c
··· 24 24 #include <linux/smp_lock.h> 25 25 #include <linux/slab.h> 26 26 #include <linux/time.h> 27 + #include <linux/string.h> 27 28 #include <sound/core.h> 28 29 #include <sound/minors.h> 29 30 #include <sound/control.h> ··· 1138 1137 goto __unlock; 1139 1138 } 1140 1139 tbl->oss_id = ch; 1141 - tbl->name = snd_kmalloc_strdup(str, GFP_KERNEL); 1140 + tbl->name = kstrdup(str, GFP_KERNEL); 1142 1141 if (! tbl->name) { 1143 1142 kfree(tbl); 1144 1143 goto __unlock;
+2 -1
sound/core/oss/pcm_oss.c
··· 33 33 #include <linux/time.h> 34 34 #include <linux/vmalloc.h> 35 35 #include <linux/moduleparam.h> 36 + #include <linux/string.h> 36 37 #include <sound/core.h> 37 38 #include <sound/minors.h> 38 39 #include <sound/pcm.h> ··· 2361 2360 for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); 2362 2361 setup1->next = setup; 2363 2362 } 2364 - template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL); 2363 + template.task_name = kstrdup(task_name, GFP_KERNEL); 2365 2364 } else { 2366 2365 buffer->error = -ENOMEM; 2367 2366 }
+1 -1
sound/core/sound.c
··· 399 399 EXPORT_SYMBOL(snd_hidden_kfree); 400 400 EXPORT_SYMBOL(snd_hidden_vmalloc); 401 401 EXPORT_SYMBOL(snd_hidden_vfree); 402 + EXPORT_SYMBOL(snd_hidden_kstrdup); 402 403 #endif 403 - EXPORT_SYMBOL(snd_kmalloc_strdup); 404 404 EXPORT_SYMBOL(copy_to_user_fromio); 405 405 EXPORT_SYMBOL(copy_from_user_toio); 406 406 /* init.c */
+2 -1
sound/core/timer.c
··· 26 26 #include <linux/slab.h> 27 27 #include <linux/time.h> 28 28 #include <linux/moduleparam.h> 29 + #include <linux/string.h> 29 30 #include <sound/core.h> 30 31 #include <sound/timer.h> 31 32 #include <sound/control.h> ··· 101 100 timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL); 102 101 if (timeri == NULL) 103 102 return NULL; 104 - timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL); 103 + timeri->owner = kstrdup(owner, GFP_KERNEL); 105 104 if (! timeri->owner) { 106 105 kfree(timeri); 107 106 return NULL;
+4 -3
sound/isa/gus/gus_mem.c
··· 21 21 22 22 #include <sound/driver.h> 23 23 #include <linux/slab.h> 24 + #include <linux/string.h> 24 25 #include <sound/core.h> 25 26 #include <sound/gus.h> 26 27 #include <sound/info.h> ··· 214 213 if (share_id != NULL) 215 214 memcpy(&block.share_id, share_id, sizeof(block.share_id)); 216 215 block.owner = owner; 217 - block.name = snd_kmalloc_strdup(name, GFP_KERNEL); 216 + block.name = kstrdup(name, GFP_KERNEL); 218 217 nblock = snd_gf1_mem_xalloc(alloc, &block); 219 218 snd_gf1_mem_lock(alloc, 1); 220 219 return nblock; ··· 254 253 if (gus->gf1.enh_mode) { 255 254 block.ptr = 0; 256 255 block.size = 1024; 257 - block.name = snd_kmalloc_strdup("InterWave LFOs", GFP_KERNEL); 256 + block.name = kstrdup("InterWave LFOs", GFP_KERNEL); 258 257 if (snd_gf1_mem_xalloc(alloc, &block) == NULL) 259 258 return -ENOMEM; 260 259 } 261 260 block.ptr = gus->gf1.default_voice_address; 262 261 block.size = 4; 263 - block.name = snd_kmalloc_strdup("Voice default (NULL's)", GFP_KERNEL); 262 + block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL); 264 263 if (snd_gf1_mem_xalloc(alloc, &block) == NULL) 265 264 return -ENOMEM; 266 265 #ifdef CONFIG_SND_DEBUG
+1 -1
sound/pci/hda/patch_realtek.c
··· 1781 1781 1782 1782 knew = &spec->kctl_alloc[spec->num_kctl_used]; 1783 1783 *knew = alc880_control_templates[type]; 1784 - knew->name = snd_kmalloc_strdup(name, GFP_KERNEL); 1784 + knew->name = kstrdup(name, GFP_KERNEL); 1785 1785 if (! knew->name) 1786 1786 return -ENOMEM; 1787 1787 knew->private_value = val;
+2 -1
sound/synth/emux/emux.c
··· 22 22 #include <linux/wait.h> 23 23 #include <linux/sched.h> 24 24 #include <linux/slab.h> 25 + #include <linux/string.h> 25 26 #include <sound/core.h> 26 27 #include <sound/emux_synth.h> 27 28 #include <linux/init.h> ··· 77 76 snd_assert(name != NULL, return -EINVAL); 78 77 79 78 emu->card = card; 80 - emu->name = snd_kmalloc_strdup(name, GFP_KERNEL); 79 + emu->name = kstrdup(name, GFP_KERNEL); 81 80 emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL); 82 81 if (emu->voices == NULL) 83 82 return -ENOMEM;