diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-01-04 23:50:23 -0800 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-01-09 08:39:04 -0800 |
commit | 16263ff6c72eb4cc00aa287230144dda12ccad12 (patch) | |
tree | b92a29f5508d3dd5f494e4399bf0be799b93e319 /block/badblocks.c | |
parent | 20a308f09e0d29ce6f5a4114cc476a998d569bfb (diff) | |
download | lwn-16263ff6c72eb4cc00aa287230144dda12ccad12.tar.gz lwn-16263ff6c72eb4cc00aa287230144dda12ccad12.zip |
block, badblocks: introduce devm_init_badblocks
Provide a devres interface for initializing a badblocks instance. The
pmem driver has several scenarios where it will be beneficial to have
this structure automatically freed when the device is disabled / fails
probe.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'block/badblocks.c')
-rw-r--r-- | block/badblocks.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/block/badblocks.c b/block/badblocks.c index 37e5c0a2ef69..7be53cb1cc3c 100644 --- a/block/badblocks.c +++ b/block/badblocks.c @@ -17,6 +17,7 @@ #include <linux/badblocks.h> #include <linux/seqlock.h> +#include <linux/device.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/stddef.h> @@ -522,24 +523,20 @@ ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, } EXPORT_SYMBOL_GPL(badblocks_store); -/** - * badblocks_init() - initialize the badblocks structure - * @bb: the badblocks structure that holds all badblock information - * @enable: weather to enable badblocks accounting - * - * Return: - * 0: success - * -ve errno: on error - */ -int badblocks_init(struct badblocks *bb, int enable) +static int __badblocks_init(struct device *dev, struct badblocks *bb, + int enable) { + bb->dev = dev; bb->count = 0; if (enable) bb->shift = 0; else bb->shift = -1; - bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (bb->page == (u64 *)0) { + if (dev) + bb->page = devm_kzalloc(dev, PAGE_SIZE, GFP_KERNEL); + else + bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!bb->page) { bb->shift = -1; return -ENOMEM; } @@ -547,8 +544,30 @@ int badblocks_init(struct badblocks *bb, int enable) return 0; } + +/** + * badblocks_init() - initialize the badblocks structure + * @bb: the badblocks structure that holds all badblock information + * @enable: weather to enable badblocks accounting + * + * Return: + * 0: success + * -ve errno: on error + */ +int badblocks_init(struct badblocks *bb, int enable) +{ + return __badblocks_init(NULL, bb, enable); +} EXPORT_SYMBOL_GPL(badblocks_init); +int devm_init_badblocks(struct device *dev, struct badblocks *bb) +{ + if (!bb) + return -EINVAL; + return __badblocks_init(dev, bb, 1); +} +EXPORT_SYMBOL_GPL(devm_init_badblocks); + /** * badblocks_exit() - free the badblocks structure * @bb: the badblocks structure that holds all badblock information @@ -557,7 +576,10 @@ void badblocks_exit(struct badblocks *bb) { if (!bb) return; - kfree(bb->page); + if (bb->dev) + devm_kfree(bb->dev, bb->page); + else + kfree(bb->page); bb->page = NULL; } EXPORT_SYMBOL_GPL(badblocks_exit); |