Add some generally-useful string replication functions which are required by call_usermodehelper_async(): void *kzmalloc(size_t size, int gfp_flags); kmalloc() then bzero(). char *kstrdup(char *p, int gfp_flags); kmalloc() then strcpy() char **kstrdup_vec(char **vec, int gfp_flags); duplicate an argv[]-style string array void kfree_strvec(char **vec); free up the result of a previous kstrdup_vec() --- 25-akpm/drivers/md/dm-ioctl.c | 17 ++---------- 25-akpm/include/linux/slab.h | 5 +++ 25-akpm/mm/slab.c | 57 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 14 deletions(-) diff -puN drivers/md/dm-ioctl.c~kstrdup-and-friends drivers/md/dm-ioctl.c --- 25/drivers/md/dm-ioctl.c~kstrdup-and-friends 2004-04-10 12:50:59.324302648 -0700 +++ 25-akpm/drivers/md/dm-ioctl.c 2004-04-10 12:50:59.341300064 -0700 @@ -118,17 +118,6 @@ static struct hash_cell *__get_uuid_cell return NULL; } -/*----------------------------------------------------------------- - * 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) { @@ -138,7 +127,7 @@ static struct hash_cell *alloc_cell(cons if (!hc) return NULL; - hc->name = kstrdup(name); + hc->name = kstrdup(name, GFP_KERNEL); if (!hc->name) { kfree(hc); return NULL; @@ -148,7 +137,7 @@ static struct hash_cell *alloc_cell(cons hc->uuid = NULL; else { - hc->uuid = kstrdup(uuid); + hc->uuid = kstrdup(uuid, GFP_KERNEL); if (!hc->uuid) { kfree(hc->name); kfree(hc); @@ -270,7 +259,7 @@ int dm_hash_rename(const char *old, cons /* * duplicate new. */ - new_name = kstrdup(new); + new_name = kstrdup(new, GFP_KERNEL); if (!new_name) return -ENOMEM; diff -puN include/linux/slab.h~kstrdup-and-friends include/linux/slab.h --- 25/include/linux/slab.h~kstrdup-and-friends 2004-04-10 12:50:59.326302344 -0700 +++ 25-akpm/include/linux/slab.h 2004-04-10 13:07:58.979291528 -0700 @@ -117,6 +117,11 @@ void ptrinfo(unsigned long addr); extern atomic_t slab_reclaim_pages; +void *kzmalloc(size_t size, int gfp_flags); +char *kstrdup(const char *p, int gfp_flags); +char **kstrdup_vec(char **vec, int gfp_flags); +void kfree_strvec(char **vec); + #endif /* __KERNEL__ */ #endif /* _LINUX_SLAB_H */ diff -puN mm/slab.c~kstrdup-and-friends mm/slab.c --- 25/mm/slab.c~kstrdup-and-friends 2004-04-10 12:50:59.328302040 -0700 +++ 25-akpm/mm/slab.c 2004-04-10 13:08:05.602284680 -0700 @@ -3009,3 +3009,60 @@ void ptrinfo(unsigned long addr) } } + +void *kzmalloc(size_t size, int gfp_flags) +{ + void *ret = kmalloc(size, gfp_flags); + if (ret) + memset(ret, 0, size); + return ret; +} +EXPORT_SYMBOL(kzmalloc); + +char *kstrdup(const char *p, int gfp_flags) +{ + char *ret = kmalloc(strlen(p) + 1, gfp_flags); + if (ret) + strcpy(ret, p); + return ret; +} +EXPORT_SYMBOL(kstrdup); + +char **kstrdup_vec(char **vec, int gfp_flags) +{ + char **ret; + int nr_strings; + int i; + + for (nr_strings = 0; vec[nr_strings]; nr_strings++) + ; + ret = kzmalloc((nr_strings + 1) * sizeof(*ret), gfp_flags); + if (ret == NULL) + goto enomem; + for (i = 0; i < nr_strings; i++) { + ret[i] = kstrdup(vec[i], gfp_flags); + if (ret[i] == NULL) + goto enomem; + } + ret[i] = NULL; + return ret; +enomem: + kfree_strvec(ret); + return NULL; +} +EXPORT_SYMBOL(kstrdup_vec); + +void kfree_strvec(char **vec) +{ + char **p; + + if (vec == NULL) + return; + p = vec; + while (*p) { + kfree(*p); + p++; + } + kfree(vec); +} +EXPORT_SYMBOL(kfree_strvec); _