diff options
author | Bartosz Golaszewski <brgl@bgdev.pl> | 2018-10-14 11:20:09 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-16 06:53:27 -0400 |
commit | 09d1ea1c7309c8ca91151778bb3efe514f2e03ed (patch) | |
tree | 98a882274dd510cebd313e0d0f89fcd0344fac37 | |
parent | 59c3f82ad1d6ed83fde9d7608afb9fb221a211ab (diff) |
devres: provide devm_kstrdup_const()
Provide a resource managed version of kstrdup_const(). This variant
internally calls devm_kstrdup() on pointers that are outside of
.rodata section and returns the string as is otherwise.
Make devm_kfree() check if the passed pointer doesn't point to .rodata
and if so - don't actually destroy the resource.
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/base/devres.c | 31 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
2 files changed, 33 insertions, 0 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 438c91a43508..4aaf00d2098b 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
13 | 13 | ||
14 | #include <asm/sections.h> | ||
15 | |||
14 | #include "base.h" | 16 | #include "base.h" |
15 | 17 | ||
16 | struct devres_node { | 18 | struct devres_node { |
@@ -823,6 +825,28 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) | |||
823 | EXPORT_SYMBOL_GPL(devm_kstrdup); | 825 | EXPORT_SYMBOL_GPL(devm_kstrdup); |
824 | 826 | ||
825 | /** | 827 | /** |
828 | * devm_kstrdup_const - resource managed conditional string duplication | ||
829 | * @dev: device for which to duplicate the string | ||
830 | * @s: the string to duplicate | ||
831 | * @gfp: the GFP mask used in the kmalloc() call when allocating memory | ||
832 | * | ||
833 | * Strings allocated by devm_kstrdup_const will be automatically freed when | ||
834 | * the associated device is detached. | ||
835 | * | ||
836 | * RETURNS: | ||
837 | * Source string if it is in .rodata section otherwise it falls back to | ||
838 | * devm_kstrdup. | ||
839 | */ | ||
840 | const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp) | ||
841 | { | ||
842 | if (is_kernel_rodata((unsigned long)s)) | ||
843 | return s; | ||
844 | |||
845 | return devm_kstrdup(dev, s, gfp); | ||
846 | } | ||
847 | EXPORT_SYMBOL_GPL(devm_kstrdup_const); | ||
848 | |||
849 | /** | ||
826 | * devm_kvasprintf - Allocate resource managed space and format a string | 850 | * devm_kvasprintf - Allocate resource managed space and format a string |
827 | * into that. | 851 | * into that. |
828 | * @dev: Device to allocate memory for | 852 | * @dev: Device to allocate memory for |
@@ -889,6 +913,13 @@ void devm_kfree(struct device *dev, const void *p) | |||
889 | { | 913 | { |
890 | int rc; | 914 | int rc; |
891 | 915 | ||
916 | /* | ||
917 | * Special case: pointer to a string in .rodata returned by | ||
918 | * devm_kstrdup_const(). | ||
919 | */ | ||
920 | if (unlikely(is_kernel_rodata((unsigned long)p))) | ||
921 | return; | ||
922 | |||
892 | rc = devres_destroy(dev, devm_kmalloc_release, | 923 | rc = devres_destroy(dev, devm_kmalloc_release, |
893 | devm_kmalloc_match, (void *)p); | 924 | devm_kmalloc_match, (void *)p); |
894 | WARN_ON(rc); | 925 | WARN_ON(rc); |
diff --git a/include/linux/device.h b/include/linux/device.h index c2022c1daef6..fecd9722400e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -696,6 +696,8 @@ static inline void *devm_kcalloc(struct device *dev, | |||
696 | } | 696 | } |
697 | extern void devm_kfree(struct device *dev, const void *p); | 697 | extern void devm_kfree(struct device *dev, const void *p); |
698 | extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; | 698 | extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; |
699 | extern const char *devm_kstrdup_const(struct device *dev, | ||
700 | const char *s, gfp_t gfp); | ||
699 | extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, | 701 | extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, |
700 | gfp_t gfp); | 702 | gfp_t gfp); |
701 | 703 | ||