summaryrefslogtreecommitdiffstats
path: root/lib/kobject.c
diff options
context:
space:
mode:
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2015-11-06 19:31:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 20:50:42 -0500
commitf773f32d71a4ed9a645634da107cd249e09e1180 (patch)
treed121a233372164a2b9d75614c9b95cce923b5584 /lib/kobject.c
parent0a9df786a6ae2f898114bdd242b64920dedf53bd (diff)
lib/kobject.c: use kvasprintf_const for formatting ->name
Sometimes kobject_set_name_vargs is called with a format string conaining no %, or a format string of precisely "%s", where the single vararg happens to point to .rodata. kvasprintf_const detects these cases for us and returns a copy of that pointer instead of duplicating the string, thus saving some run-time memory. Otherwise, it falls back to kvasprintf. We just need to always deallocate ->name using kfree_const. Unfortunately, the dance we need to do to perform the '/' -> '!' sanitization makes the resulting code rather ugly. I instrumented kstrdup_const to provide some statistics on the memory saved, and for me this gave an additional ~14KB after boot (306KB was already saved; this patch bumped that to 320KB). I have KMALLOC_SHIFT_LOW==3, and since 80% of the kvasprintf_const hits were satisfied by an 8-byte allocation, the 14K would roughly be quadrupled when KMALLOC_SHIFT_LOW==5. Whether these numbers are sufficient to justify the ugliness I'll leave to others to decide. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/kobject.c')
-rw-r--r--lib/kobject.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/lib/kobject.c b/lib/kobject.c
index 055407746266..7cbccd2b4c72 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -257,18 +257,32 @@ static int kobject_add_internal(struct kobject *kobj)
257int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, 257int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
258 va_list vargs) 258 va_list vargs)
259{ 259{
260 char *s; 260 const char *s;
261 261
262 if (kobj->name && !fmt) 262 if (kobj->name && !fmt)
263 return 0; 263 return 0;
264 264
265 s = kvasprintf(GFP_KERNEL, fmt, vargs); 265 s = kvasprintf_const(GFP_KERNEL, fmt, vargs);
266 if (!s) 266 if (!s)
267 return -ENOMEM; 267 return -ENOMEM;
268 268
269 /* ewww... some of these buggers have '/' in the name ... */ 269 /*
270 strreplace(s, '/', '!'); 270 * ewww... some of these buggers have '/' in the name ... If
271 kfree(kobj->name); 271 * that's the case, we need to make sure we have an actual
272 * allocated copy to modify, since kvasprintf_const may have
273 * returned something from .rodata.
274 */
275 if (strchr(s, '/')) {
276 char *t;
277
278 t = kstrdup(s, GFP_KERNEL);
279 kfree_const(s);
280 if (!t)
281 return -ENOMEM;
282 strreplace(t, '/', '!');
283 s = t;
284 }
285 kfree_const(kobj->name);
272 kobj->name = s; 286 kobj->name = s;
273 287
274 return 0; 288 return 0;
@@ -466,7 +480,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
466 envp[0] = devpath_string; 480 envp[0] = devpath_string;
467 envp[1] = NULL; 481 envp[1] = NULL;
468 482
469 name = dup_name = kstrdup(new_name, GFP_KERNEL); 483 name = dup_name = kstrdup_const(new_name, GFP_KERNEL);
470 if (!name) { 484 if (!name) {
471 error = -ENOMEM; 485 error = -ENOMEM;
472 goto out; 486 goto out;
@@ -486,7 +500,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
486 kobject_uevent_env(kobj, KOBJ_MOVE, envp); 500 kobject_uevent_env(kobj, KOBJ_MOVE, envp);
487 501
488out: 502out:
489 kfree(dup_name); 503 kfree_const(dup_name);
490 kfree(devpath_string); 504 kfree(devpath_string);
491 kfree(devpath); 505 kfree(devpath);
492 kobject_put(kobj); 506 kobject_put(kobj);
@@ -634,7 +648,7 @@ static void kobject_cleanup(struct kobject *kobj)
634 /* free name if we allocated it */ 648 /* free name if we allocated it */
635 if (name) { 649 if (name) {
636 pr_debug("kobject: '%s': free name\n", name); 650 pr_debug("kobject: '%s': free name\n", name);
637 kfree(name); 651 kfree_const(name);
638 } 652 }
639} 653}
640 654