diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-05-15 13:44:08 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-05-20 13:31:53 -0700 |
commit | 19051c5035d217e572672a2ca9db06c1cef50e9b (patch) | |
tree | 9fef0047e070c977463a85d5cbd0f9479694d286 | |
parent | 8882b39421bae317e3ee864edd845e994307ce16 (diff) | |
download | lwn-19051c5035d217e572672a2ca9db06c1cef50e9b.tar.gz lwn-19051c5035d217e572672a2ca9db06c1cef50e9b.zip |
mm: bdi: fix race in bdi_class device creation
There is a race from when a device is created with device_create() and
then the drvdata is set with a call to dev_set_drvdata() in which a
sysfs file could be open, yet the drvdata will be NULL, causing all
sorts of bad things to happen.
This patch fixes the problem by using the new function,
device_create_vargs().
Many thanks to Arthur Jones <ajones@riverbed.com> for reporting the bug,
and testing patches out.
Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Arthur Jones <ajones@riverbed.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | mm/backing-dev.c | 12 |
1 files changed, 2 insertions, 10 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 7c4f9e097095..f2e574dbc300 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -172,30 +172,22 @@ postcore_initcall(bdi_class_init); int bdi_register(struct backing_dev_info *bdi, struct device *parent, const char *fmt, ...) { - char *name; va_list args; int ret = 0; struct device *dev; va_start(args, fmt); - name = kvasprintf(GFP_KERNEL, fmt, args); + dev = device_create_vargs(bdi_class, parent, MKDEV(0, 0), bdi, fmt, args); va_end(args); - - if (!name) - return -ENOMEM; - - dev = device_create(bdi_class, parent, MKDEV(0, 0), name); if (IS_ERR(dev)) { ret = PTR_ERR(dev); goto exit; } bdi->dev = dev; - dev_set_drvdata(bdi->dev, bdi); - bdi_debug_register(bdi, name); + bdi_debug_register(bdi, dev_name(dev)); exit: - kfree(name); return ret; } EXPORT_SYMBOL(bdi_register); |