aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorMichal Nazarewicz <m.nazarewicz@samsung.com>2010-05-12 06:51:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:45 -0400
commitb9e000884e50bf6b25a92a3f3580e1d14fe01591 (patch)
tree05188e049219fed1cacc50f09e1d62a296d95bbe /drivers/usb/gadget
parentf537da685c35a81a75f6067751bddb902c8adb68 (diff)
USB: gadget: f_mass_storage: fix in error recovery
In to places in fsg_common_init() an unconditional call to kfree() on common was performed in error recovery which is not a valid behaviour since fsg_common structure is not always allocated by fsg_common_init(). To fix, the calls has been replaced with a goto to a proper error recovery which does the correct thing. Also, refactored fsg_common_release() function. Signed-off-by: Michal Nazarewicz <mina86@mina86.com> Reviewed-by: Viral Mehta <viral.mehta@lntinfotech.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/f_mass_storage.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 6cfd2f428d38..7d05a0be5c60 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2742,10 +2742,8 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2742 /* Maybe allocate device-global string IDs, and patch descriptors */ 2742 /* Maybe allocate device-global string IDs, and patch descriptors */
2743 if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { 2743 if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
2744 rc = usb_string_id(cdev); 2744 rc = usb_string_id(cdev);
2745 if (rc < 0) { 2745 if (unlikely(rc < 0))
2746 kfree(common); 2746 goto error_release;
2747 return ERR_PTR(rc);
2748 }
2749 fsg_strings[FSG_STRING_INTERFACE].id = rc; 2747 fsg_strings[FSG_STRING_INTERFACE].id = rc;
2750 fsg_intf_desc.iInterface = rc; 2748 fsg_intf_desc.iInterface = rc;
2751 } 2749 }
@@ -2753,9 +2751,9 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
2753 /* Create the LUNs, open their backing files, and register the 2751 /* Create the LUNs, open their backing files, and register the
2754 * LUN devices in sysfs. */ 2752 * LUN devices in sysfs. */
2755 curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL); 2753 curlun = kzalloc(nluns * sizeof *curlun, GFP_KERNEL);
2756 if (!curlun) { 2754 if (unlikely(!curlun)) {
2757 kfree(common); 2755 rc = -ENOMEM;
2758 return ERR_PTR(-ENOMEM); 2756 goto error_release;
2759 } 2757 }
2760 common->luns = curlun; 2758 common->luns = curlun;
2761 2759
@@ -2914,11 +2912,7 @@ error_release:
2914 2912
2915static void fsg_common_release(struct kref *ref) 2913static void fsg_common_release(struct kref *ref)
2916{ 2914{
2917 struct fsg_common *common = 2915 struct fsg_common *common = container_of(ref, struct fsg_common, ref);
2918 container_of(ref, struct fsg_common, ref);
2919 unsigned i = common->nluns;
2920 struct fsg_lun *lun = common->luns;
2921 struct fsg_buffhd *bh;
2922 2916
2923 /* If the thread isn't already dead, tell it to exit now */ 2917 /* If the thread isn't already dead, tell it to exit now */
2924 if (common->state != FSG_STATE_TERMINATED) { 2918 if (common->state != FSG_STATE_TERMINATED) {
@@ -2929,23 +2923,28 @@ static void fsg_common_release(struct kref *ref)
2929 complete(&common->thread_notifier); 2923 complete(&common->thread_notifier);
2930 } 2924 }
2931 2925
2932 /* Beware tempting for -> do-while optimization: when in error 2926 if (likely(common->luns)) {
2933 * recovery nluns may be zero. */ 2927 struct fsg_lun *lun = common->luns;
2928 unsigned i = common->nluns;
2934 2929
2935 for (; i; --i, ++lun) { 2930 /* In error recovery common->nluns may be zero. */
2936 device_remove_file(&lun->dev, &dev_attr_ro); 2931 for (; i; --i, ++lun) {
2937 device_remove_file(&lun->dev, &dev_attr_file); 2932 device_remove_file(&lun->dev, &dev_attr_ro);
2938 fsg_lun_close(lun); 2933 device_remove_file(&lun->dev, &dev_attr_file);
2939 device_unregister(&lun->dev); 2934 fsg_lun_close(lun);
2940 } 2935 device_unregister(&lun->dev);
2936 }
2941 2937
2942 kfree(common->luns); 2938 kfree(common->luns);
2939 }
2943 2940
2944 i = FSG_NUM_BUFFERS; 2941 {
2945 bh = common->buffhds; 2942 struct fsg_buffhd *bh = common->buffhds;
2946 do { 2943 unsigned i = FSG_NUM_BUFFERS;
2947 kfree(bh->buf); 2944 do {
2948 } while (++bh, --i); 2945 kfree(bh->buf);
2946 } while (++bh, --i);
2947 }
2949 2948
2950 if (common->free_storage_on_release) 2949 if (common->free_storage_on_release)
2951 kfree(common); 2950 kfree(common);