diff options
author | Jan Beulich <jbeulich@novell.com> | 2010-08-07 12:31:12 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-08-07 12:31:12 -0400 |
commit | 5d7ed20e822ef82117a4d9928b030fa0247b789d (patch) | |
tree | dff5db85b4c7ff8f978a3f737c5c595baf82519b /drivers | |
parent | 0e34582699392d67910bd3919bc8fd9bedce115e (diff) |
blkfront: don't access freed struct xenbus_device
Unfortunately commit "blkfront: fixes for 'xm block-detach ... --force'"
still wasn't quite right - there was a reference to freed memory left
from blkfront_closing().
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xen-blkfront.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 22091e4e401f..60006b730872 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -981,13 +981,11 @@ static void blkfront_connect(struct blkfront_info *info) | |||
981 | * the backend. Once is this done, we can switch to Closed in | 981 | * the backend. Once is this done, we can switch to Closed in |
982 | * acknowledgement. | 982 | * acknowledgement. |
983 | */ | 983 | */ |
984 | static void blkfront_closing(struct xenbus_device *dev) | 984 | static void blkfront_closing(struct blkfront_info *info) |
985 | { | 985 | { |
986 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | ||
987 | unsigned int minor, nr_minors; | 986 | unsigned int minor, nr_minors; |
988 | unsigned long flags; | 987 | unsigned long flags; |
989 | 988 | ||
990 | dev_dbg(&dev->dev, "blkfront_closing: %s removed\n", dev->nodename); | ||
991 | 989 | ||
992 | if (info->rq == NULL) | 990 | if (info->rq == NULL) |
993 | goto out; | 991 | goto out; |
@@ -1013,7 +1011,8 @@ static void blkfront_closing(struct xenbus_device *dev) | |||
1013 | xlbd_release_minors(minor, nr_minors); | 1011 | xlbd_release_minors(minor, nr_minors); |
1014 | 1012 | ||
1015 | out: | 1013 | out: |
1016 | xenbus_frontend_closed(dev); | 1014 | if (info->xbdev) |
1015 | xenbus_frontend_closed(info->xbdev); | ||
1017 | } | 1016 | } |
1018 | 1017 | ||
1019 | /** | 1018 | /** |
@@ -1053,7 +1052,7 @@ static void blkback_changed(struct xenbus_device *dev, | |||
1053 | xenbus_dev_error(dev, -EBUSY, | 1052 | xenbus_dev_error(dev, -EBUSY, |
1054 | "Device in use; refusing to close"); | 1053 | "Device in use; refusing to close"); |
1055 | else | 1054 | else |
1056 | blkfront_closing(dev); | 1055 | blkfront_closing(info); |
1057 | mutex_unlock(&bd->bd_mutex); | 1056 | mutex_unlock(&bd->bd_mutex); |
1058 | bdput(bd); | 1057 | bdput(bd); |
1059 | break; | 1058 | break; |
@@ -1071,7 +1070,7 @@ static int blkfront_remove(struct xenbus_device *dev) | |||
1071 | if(info->users == 0) | 1070 | if(info->users == 0) |
1072 | kfree(info); | 1071 | kfree(info); |
1073 | else | 1072 | else |
1074 | info->is_ready = -1; | 1073 | info->xbdev = NULL; |
1075 | 1074 | ||
1076 | return 0; | 1075 | return 0; |
1077 | } | 1076 | } |
@@ -1080,22 +1079,21 @@ static int blkfront_is_ready(struct xenbus_device *dev) | |||
1080 | { | 1079 | { |
1081 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | 1080 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); |
1082 | 1081 | ||
1083 | return info->is_ready > 0; | 1082 | return info->is_ready && info->xbdev; |
1084 | } | 1083 | } |
1085 | 1084 | ||
1086 | static int blkif_open(struct block_device *bdev, fmode_t mode) | 1085 | static int blkif_open(struct block_device *bdev, fmode_t mode) |
1087 | { | 1086 | { |
1088 | struct blkfront_info *info = bdev->bd_disk->private_data; | 1087 | struct blkfront_info *info = bdev->bd_disk->private_data; |
1089 | int ret = 0; | 1088 | |
1089 | if (!info->xbdev) | ||
1090 | return -ENODEV; | ||
1090 | 1091 | ||
1091 | lock_kernel(); | 1092 | lock_kernel(); |
1092 | if (info->is_ready < 0) | 1093 | info->users++; |
1093 | ret = -ENODEV; | ||
1094 | else | ||
1095 | info->users++; | ||
1096 | unlock_kernel(); | 1094 | unlock_kernel(); |
1097 | 1095 | ||
1098 | return ret; | 1096 | return 0; |
1099 | } | 1097 | } |
1100 | 1098 | ||
1101 | static int blkif_release(struct gendisk *disk, fmode_t mode) | 1099 | static int blkif_release(struct gendisk *disk, fmode_t mode) |
@@ -1108,13 +1106,13 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) | |||
1108 | have ignored this request initially, as the device was | 1106 | have ignored this request initially, as the device was |
1109 | still mounted. */ | 1107 | still mounted. */ |
1110 | struct xenbus_device *dev = info->xbdev; | 1108 | struct xenbus_device *dev = info->xbdev; |
1111 | enum xenbus_state state = xenbus_read_driver_state(dev->otherend); | ||
1112 | 1109 | ||
1113 | if(info->is_ready < 0) { | 1110 | if (!dev) { |
1114 | blkfront_closing(dev); | 1111 | blkfront_closing(info); |
1115 | kfree(info); | 1112 | kfree(info); |
1116 | } else if (state == XenbusStateClosing && info->is_ready) | 1113 | } else if (xenbus_read_driver_state(dev->otherend) |
1117 | blkfront_closing(dev); | 1114 | == XenbusStateClosing && info->is_ready) |
1115 | blkfront_closing(info); | ||
1118 | } | 1116 | } |
1119 | unlock_kernel(); | 1117 | unlock_kernel(); |
1120 | return 0; | 1118 | return 0; |