Skip to content

Commit

Permalink
[PATCH] create a kstrdup library function
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Paulo Marques authored and Linus Torvalds committed Jun 23, 2005
1 parent 991114c commit 543537b
Show file tree
Hide file tree
Showing 21 changed files with 75 additions and 94 deletions.
14 changes: 3 additions & 11 deletions drivers/md/dm-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,6 @@ static struct hash_cell *__get_uuid_cell(const char *str)
/*-----------------------------------------------------------------
* Inserting, removing and renaming a device.
*---------------------------------------------------------------*/
static inline char *kstrdup(const char *str)
{
char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
if (r)
strcpy(r, str);
return r;
}

static struct hash_cell *alloc_cell(const char *name, const char *uuid,
struct mapped_device *md)
{
Expand All @@ -139,7 +131,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid,
if (!hc)
return NULL;

hc->name = kstrdup(name);
hc->name = kstrdup(name, GFP_KERNEL);
if (!hc->name) {
kfree(hc);
return NULL;
Expand All @@ -149,7 +141,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid,
hc->uuid = NULL;

else {
hc->uuid = kstrdup(uuid);
hc->uuid = kstrdup(uuid, GFP_KERNEL);
if (!hc->uuid) {
kfree(hc->name);
kfree(hc);
Expand Down Expand Up @@ -273,7 +265,7 @@ static int dm_hash_rename(const char *old, const char *new)
/*
* duplicate new.
*/
new_name = kstrdup(new);
new_name = kstrdup(new, GFP_KERNEL);
if (!new_name)
return -ENOMEM;

Expand Down
18 changes: 5 additions & 13 deletions drivers/parport/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,6 @@ static void pretty_print(struct parport *port, int device)
printk("\n");
}

static char *strdup(char *str)
{
int n = strlen(str)+1;
char *s = kmalloc(n, GFP_KERNEL);
if (!s) return NULL;
return strcpy(s, str);
}

static void parse_data(struct parport *port, int device, char *str)
{
char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
Expand Down Expand Up @@ -88,16 +80,16 @@ static void parse_data(struct parport *port, int device, char *str)
if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
if (info->mfr)
kfree (info->mfr);
info->mfr = strdup(sep);
info->mfr = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
if (info->model)
kfree (info->model);
info->model = strdup(sep);
info->model = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
int i;
if (info->class_name)
kfree (info->class_name);
info->class_name = strdup(sep);
info->class_name = kstrdup(sep, GFP_KERNEL);
for (u = sep; *u; u++)
*u = toupper(*u);
for (i = 0; classes[i].token; i++) {
Expand All @@ -112,15 +104,15 @@ static void parse_data(struct parport *port, int device, char *str)
!strcmp(p, "COMMAND SET")) {
if (info->cmdset)
kfree (info->cmdset);
info->cmdset = strdup(sep);
info->cmdset = kstrdup(sep, GFP_KERNEL);
/* if it speaks printer language, it's
probably a printer */
if (strstr(sep, "PJL") || strstr(sep, "PCL"))
guessed_class = PARPORT_CLASS_PRINTER;
} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
if (info->description)
kfree (info->description);
info->description = strdup(sep);
info->description = kstrdup(sep, GFP_KERNEL);
}
}
rock_on:
Expand Down
4 changes: 0 additions & 4 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -925,10 +925,6 @@ extern int skb_checksum_help(struct sk_buff *skb, int inward);
extern void net_enable_timestamp(void);
extern void net_disable_timestamp(void);

#ifdef CONFIG_SYSCTL
extern char *net_sysctl_strdup(const char *s);
#endif

#endif /* __KERNEL__ */

#endif /* _LINUX_DEV_H */
2 changes: 2 additions & 0 deletions include/linux/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
extern void * memchr(const void *,int,__kernel_size_t);
#endif

extern char *kstrdup(const char *s, int gfp);

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion include/sound/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ void *snd_hidden_kcalloc(size_t n, size_t size, int flags);
void snd_hidden_kfree(const void *obj);
void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj);
char *snd_hidden_kstrdup(const char *s, int flags);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
#define kfree(obj) snd_hidden_kfree(obj)
Expand All @@ -301,6 +302,7 @@ void snd_hidden_vfree(void *obj);
#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size)
#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vfree_nocheck(obj) snd_wrapper_vfree(obj)
#define kstrdup(s, flags) snd_hidden_kstrdup(s, flags)
#else
#define snd_memory_init() /*NOP*/
#define snd_memory_done() /*NOP*/
Expand All @@ -311,7 +313,6 @@ void snd_hidden_vfree(void *obj);
#define kfree_nocheck(obj) kfree(obj)
#define vfree_nocheck(obj) vfree(obj)
#endif
char *snd_kmalloc_strdup(const char *string, int flags);
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count);
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count);

Expand Down
24 changes: 24 additions & 0 deletions mm/slab.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#include <linux/sysctl.h>
#include <linux/module.h>
#include <linux/rcupdate.h>
#include <linux/string.h>

#include <asm/uaccess.h>
#include <asm/cacheflush.h>
Expand Down Expand Up @@ -3082,3 +3083,26 @@ unsigned int ksize(const void *objp)

return size;
}


/*
* kstrdup - allocate space for and copy an existing string
*
* @s: the string to duplicate
* @gfp: the GFP mask used in the kmalloc() call when allocating memory
*/
char *kstrdup(const char *s, int gfp)
{
size_t len;
char *buf;

if (!s)
return NULL;

len = strlen(s) + 1;
buf = kmalloc(len, gfp);
if (buf)
memcpy(buf, s, len);
return buf;
}
EXPORT_SYMBOL(kstrdup);
3 changes: 2 additions & 1 deletion net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>

#define NEIGH_DEBUG 1

Expand Down Expand Up @@ -2592,7 +2593,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
t->neigh_vars[17].extra1 = dev;
}

dev_name = net_sysctl_strdup(dev_name_source);
dev_name = kstrdup(dev_name_source, GFP_KERNEL);
if (!dev_name) {
err = -ENOBUFS;
goto free;
Expand Down
15 changes: 0 additions & 15 deletions net/core/sysctl_net_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ extern int sysctl_somaxconn;
extern char sysctl_divert_version[];
#endif /* CONFIG_NET_DIVERT */

/*
* This strdup() is used for creating copies of network
* device names to be handed over to sysctl.
*/

char *net_sysctl_strdup(const char *s)
{
char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
if (rv)
strcpy(rv, s);
return rv;
}

ctl_table core_table[] = {
#ifdef CONFIG_NET
{
Expand Down Expand Up @@ -177,6 +164,4 @@ ctl_table core_table[] = {
{ .ctl_name = 0 }
};

EXPORT_SYMBOL(net_sysctl_strdup);

#endif
2 changes: 1 addition & 1 deletion net/ipv4/devinet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
* by sysctl and we wouldn't want anyone to change it under our feet
* (see SIOCSIFNAME).
*/
dev_name = net_sysctl_strdup(dev_name);
dev_name = kstrdup(dev_name, GFP_KERNEL);
if (!dev_name)
goto free;

Expand Down
3 changes: 2 additions & 1 deletion net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#endif
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/string.h>

#include <net/sock.h>
#include <net/snmp.h>
Expand Down Expand Up @@ -3437,7 +3438,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
* by sysctl and we wouldn't want anyone to change it under our feet
* (see SIOCSIFNAME).
*/
dev_name = net_sysctl_strdup(dev_name);
dev_name = kstrdup(dev_name, GFP_KERNEL);
if (!dev_name)
goto free;

Expand Down
11 changes: 2 additions & 9 deletions net/sunrpc/svcauth_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/seq_file.h>
#include <linux/hash.h>
#include <linux/string.h>

#define RPCDBG_FACILITY RPCDBG_AUTH

Expand All @@ -20,14 +21,6 @@
*/


static char *strdup(char *s)
{
char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
if (rv)
strcpy(rv, s);
return rv;
}

struct unix_domain {
struct auth_domain h;
int addr_changes;
Expand Down Expand Up @@ -55,7 +48,7 @@ struct auth_domain *unix_domain_find(char *name)
if (new == NULL)
return NULL;
cache_init(&new->h.h);
new->h.name = strdup(name);
new->h.name = kstrdup(name, GFP_KERNEL);
new->h.flavour = RPC_AUTH_UNIX;
new->addr_changes = 0;
new->h.h.expiry_time = NEVER;
Expand Down
3 changes: 2 additions & 1 deletion sound/core/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/vmalloc.h>
#include <linux/time.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
Expand Down Expand Up @@ -754,7 +755,7 @@ static snd_info_entry_t *snd_info_create_entry(const char *name)
entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
return NULL;
entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
entry->name = kstrdup(name, GFP_KERNEL);
if (entry->name == NULL) {
kfree(entry);
return NULL;
Expand Down
3 changes: 2 additions & 1 deletion sound/core/info_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sound/driver.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
Expand Down Expand Up @@ -51,7 +52,7 @@ int snd_oss_info_register(int dev, int num, char *string)
x = NULL;
}
} else {
x = snd_kmalloc_strdup(string, GFP_KERNEL);
x = kstrdup(string, GFP_KERNEL);
if (x == NULL) {
up(&strings);
return -ENOMEM;
Expand Down
41 changes: 14 additions & 27 deletions sound/core/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,20 @@ void snd_hidden_vfree(void *obj)
snd_wrapper_vfree(obj);
}

char *snd_hidden_kstrdup(const char *s, int flags)
{
int len;
char *buf;

if (!s) return NULL;

len = strlen(s) + 1;
buf = _snd_kmalloc(len, flags);
if (buf)
memcpy(buf, s, len);
return buf;
}

static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
{
snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc);
Expand Down Expand Up @@ -214,35 +228,8 @@ int __exit snd_memory_info_done(void)
return 0;
}

#else

#define _snd_kmalloc kmalloc

#endif /* CONFIG_SND_DEBUG_MEMORY */

/**
* snd_kmalloc_strdup - copy the string
* @string: the original string
* @flags: allocation conditions, GFP_XXX
*
* Allocates a memory chunk via kmalloc() and copies the string to it.
*
* Returns the pointer, or NULL if no enoguh memory.
*/
char *snd_kmalloc_strdup(const char *string, int flags)
{
size_t len;
char *ptr;

if (!string)
return NULL;
len = strlen(string) + 1;
ptr = _snd_kmalloc(len, flags);
if (ptr)
memcpy(ptr, string, len);
return ptr;
}

/**
* copy_to_user_fromio - copy data from mmio-space to user-space
* @dst: the destination pointer on user-space
Expand Down
3 changes: 2 additions & 1 deletion sound/core/oss/mixer_oss.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/control.h>
Expand Down Expand Up @@ -1137,7 +1138,7 @@ static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
goto __unlock;
}
tbl->oss_id = ch;
tbl->name = snd_kmalloc_strdup(str, GFP_KERNEL);
tbl->name = kstrdup(str, GFP_KERNEL);
if (! tbl->name) {
kfree(tbl);
goto __unlock;
Expand Down
Loading

0 comments on commit 543537b

Please sign in to comment.