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-12 22:50:12.631976112 -0700
+++ 25-akpm/drivers/md/dm-ioctl.c	2004-04-12 22:50:12.638975048 -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-12 22:50:12.632975960 -0700
+++ 25-akpm/include/linux/slab.h	2004-04-12 22:50:12.639974896 -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-12 22:50:12.634975656 -0700
+++ 25-akpm/mm/slab.c	2004-04-12 22:50:12.652972920 -0700
@@ -2973,3 +2973,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);

_