diff options
Diffstat (limited to 'drivers/block/xen-blkfront.c')
-rw-r--r-- | drivers/block/xen-blkfront.c | 403 |
1 files changed, 300 insertions, 103 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index f63ac3d1f8a4..ac1b682edecb 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/cdrom.h> | 41 | #include <linux/cdrom.h> |
42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/smp_lock.h> | ||
44 | #include <linux/scatterlist.h> | 45 | #include <linux/scatterlist.h> |
45 | 46 | ||
46 | #include <xen/xen.h> | 47 | #include <xen/xen.h> |
@@ -79,6 +80,7 @@ static const struct block_device_operations xlvbd_block_fops; | |||
79 | */ | 80 | */ |
80 | struct blkfront_info | 81 | struct blkfront_info |
81 | { | 82 | { |
83 | struct mutex mutex; | ||
82 | struct xenbus_device *xbdev; | 84 | struct xenbus_device *xbdev; |
83 | struct gendisk *gd; | 85 | struct gendisk *gd; |
84 | int vdevice; | 86 | int vdevice; |
@@ -95,16 +97,14 @@ struct blkfront_info | |||
95 | unsigned long shadow_free; | 97 | unsigned long shadow_free; |
96 | int feature_barrier; | 98 | int feature_barrier; |
97 | int is_ready; | 99 | int is_ready; |
98 | |||
99 | /** | ||
100 | * The number of people holding this device open. We won't allow a | ||
101 | * hot-unplug unless this is 0. | ||
102 | */ | ||
103 | int users; | ||
104 | }; | 100 | }; |
105 | 101 | ||
106 | static DEFINE_SPINLOCK(blkif_io_lock); | 102 | static DEFINE_SPINLOCK(blkif_io_lock); |
107 | 103 | ||
104 | static unsigned int nr_minors; | ||
105 | static unsigned long *minors; | ||
106 | static DEFINE_SPINLOCK(minor_lock); | ||
107 | |||
108 | #define MAXIMUM_OUTSTANDING_BLOCK_REQS \ | 108 | #define MAXIMUM_OUTSTANDING_BLOCK_REQS \ |
109 | (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE) | 109 | (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE) |
110 | #define GRANT_INVALID_REF 0 | 110 | #define GRANT_INVALID_REF 0 |
@@ -139,6 +139,55 @@ static void add_id_to_freelist(struct blkfront_info *info, | |||
139 | info->shadow_free = id; | 139 | info->shadow_free = id; |
140 | } | 140 | } |
141 | 141 | ||
142 | static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) | ||
143 | { | ||
144 | unsigned int end = minor + nr; | ||
145 | int rc; | ||
146 | |||
147 | if (end > nr_minors) { | ||
148 | unsigned long *bitmap, *old; | ||
149 | |||
150 | bitmap = kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap), | ||
151 | GFP_KERNEL); | ||
152 | if (bitmap == NULL) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | spin_lock(&minor_lock); | ||
156 | if (end > nr_minors) { | ||
157 | old = minors; | ||
158 | memcpy(bitmap, minors, | ||
159 | BITS_TO_LONGS(nr_minors) * sizeof(*bitmap)); | ||
160 | minors = bitmap; | ||
161 | nr_minors = BITS_TO_LONGS(end) * BITS_PER_LONG; | ||
162 | } else | ||
163 | old = bitmap; | ||
164 | spin_unlock(&minor_lock); | ||
165 | kfree(old); | ||
166 | } | ||
167 | |||
168 | spin_lock(&minor_lock); | ||
169 | if (find_next_bit(minors, end, minor) >= end) { | ||
170 | for (; minor < end; ++minor) | ||
171 | __set_bit(minor, minors); | ||
172 | rc = 0; | ||
173 | } else | ||
174 | rc = -EBUSY; | ||
175 | spin_unlock(&minor_lock); | ||
176 | |||
177 | return rc; | ||
178 | } | ||
179 | |||
180 | static void xlbd_release_minors(unsigned int minor, unsigned int nr) | ||
181 | { | ||
182 | unsigned int end = minor + nr; | ||
183 | |||
184 | BUG_ON(end > nr_minors); | ||
185 | spin_lock(&minor_lock); | ||
186 | for (; minor < end; ++minor) | ||
187 | __clear_bit(minor, minors); | ||
188 | spin_unlock(&minor_lock); | ||
189 | } | ||
190 | |||
142 | static void blkif_restart_queue_callback(void *arg) | 191 | static void blkif_restart_queue_callback(void *arg) |
143 | { | 192 | { |
144 | struct blkfront_info *info = (struct blkfront_info *)arg; | 193 | struct blkfront_info *info = (struct blkfront_info *)arg; |
@@ -239,7 +288,7 @@ static int blkif_queue_request(struct request *req) | |||
239 | 288 | ||
240 | ring_req->operation = rq_data_dir(req) ? | 289 | ring_req->operation = rq_data_dir(req) ? |
241 | BLKIF_OP_WRITE : BLKIF_OP_READ; | 290 | BLKIF_OP_WRITE : BLKIF_OP_READ; |
242 | if (blk_barrier_rq(req)) | 291 | if (req->cmd_flags & REQ_HARDBARRIER) |
243 | ring_req->operation = BLKIF_OP_WRITE_BARRIER; | 292 | ring_req->operation = BLKIF_OP_WRITE_BARRIER; |
244 | 293 | ||
245 | ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); | 294 | ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); |
@@ -310,7 +359,7 @@ static void do_blkif_request(struct request_queue *rq) | |||
310 | 359 | ||
311 | blk_start_request(req); | 360 | blk_start_request(req); |
312 | 361 | ||
313 | if (!blk_fs_request(req)) { | 362 | if (req->cmd_type != REQ_TYPE_FS) { |
314 | __blk_end_request_all(req, -EIO); | 363 | __blk_end_request_all(req, -EIO); |
315 | continue; | 364 | continue; |
316 | } | 365 | } |
@@ -372,17 +421,22 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) | |||
372 | static int xlvbd_barrier(struct blkfront_info *info) | 421 | static int xlvbd_barrier(struct blkfront_info *info) |
373 | { | 422 | { |
374 | int err; | 423 | int err; |
424 | const char *barrier; | ||
375 | 425 | ||
376 | err = blk_queue_ordered(info->rq, | 426 | switch (info->feature_barrier) { |
377 | info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, | 427 | case QUEUE_ORDERED_DRAIN: barrier = "enabled (drain)"; break; |
378 | NULL); | 428 | case QUEUE_ORDERED_TAG: barrier = "enabled (tag)"; break; |
429 | case QUEUE_ORDERED_NONE: barrier = "disabled"; break; | ||
430 | default: return -EINVAL; | ||
431 | } | ||
432 | |||
433 | err = blk_queue_ordered(info->rq, info->feature_barrier); | ||
379 | 434 | ||
380 | if (err) | 435 | if (err) |
381 | return err; | 436 | return err; |
382 | 437 | ||
383 | printk(KERN_INFO "blkfront: %s: barriers %s\n", | 438 | printk(KERN_INFO "blkfront: %s: barriers %s\n", |
384 | info->gd->disk_name, | 439 | info->gd->disk_name, barrier); |
385 | info->feature_barrier ? "enabled" : "disabled"); | ||
386 | return 0; | 440 | return 0; |
387 | } | 441 | } |
388 | 442 | ||
@@ -418,9 +472,14 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
418 | if ((minor % nr_parts) == 0) | 472 | if ((minor % nr_parts) == 0) |
419 | nr_minors = nr_parts; | 473 | nr_minors = nr_parts; |
420 | 474 | ||
475 | err = xlbd_reserve_minors(minor, nr_minors); | ||
476 | if (err) | ||
477 | goto out; | ||
478 | err = -ENODEV; | ||
479 | |||
421 | gd = alloc_disk(nr_minors); | 480 | gd = alloc_disk(nr_minors); |
422 | if (gd == NULL) | 481 | if (gd == NULL) |
423 | goto out; | 482 | goto release; |
424 | 483 | ||
425 | offset = minor / nr_parts; | 484 | offset = minor / nr_parts; |
426 | 485 | ||
@@ -451,14 +510,13 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
451 | 510 | ||
452 | if (xlvbd_init_blk_queue(gd, sector_size)) { | 511 | if (xlvbd_init_blk_queue(gd, sector_size)) { |
453 | del_gendisk(gd); | 512 | del_gendisk(gd); |
454 | goto out; | 513 | goto release; |
455 | } | 514 | } |
456 | 515 | ||
457 | info->rq = gd->queue; | 516 | info->rq = gd->queue; |
458 | info->gd = gd; | 517 | info->gd = gd; |
459 | 518 | ||
460 | if (info->feature_barrier) | 519 | xlvbd_barrier(info); |
461 | xlvbd_barrier(info); | ||
462 | 520 | ||
463 | if (vdisk_info & VDISK_READONLY) | 521 | if (vdisk_info & VDISK_READONLY) |
464 | set_disk_ro(gd, 1); | 522 | set_disk_ro(gd, 1); |
@@ -471,10 +529,45 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
471 | 529 | ||
472 | return 0; | 530 | return 0; |
473 | 531 | ||
532 | release: | ||
533 | xlbd_release_minors(minor, nr_minors); | ||
474 | out: | 534 | out: |
475 | return err; | 535 | return err; |
476 | } | 536 | } |
477 | 537 | ||
538 | static void xlvbd_release_gendisk(struct blkfront_info *info) | ||
539 | { | ||
540 | unsigned int minor, nr_minors; | ||
541 | unsigned long flags; | ||
542 | |||
543 | if (info->rq == NULL) | ||
544 | return; | ||
545 | |||
546 | spin_lock_irqsave(&blkif_io_lock, flags); | ||
547 | |||
548 | /* No more blkif_request(). */ | ||
549 | blk_stop_queue(info->rq); | ||
550 | |||
551 | /* No more gnttab callback work. */ | ||
552 | gnttab_cancel_free_callback(&info->callback); | ||
553 | spin_unlock_irqrestore(&blkif_io_lock, flags); | ||
554 | |||
555 | /* Flush gnttab callback work. Must be done with no locks held. */ | ||
556 | flush_scheduled_work(); | ||
557 | |||
558 | del_gendisk(info->gd); | ||
559 | |||
560 | minor = info->gd->first_minor; | ||
561 | nr_minors = info->gd->minors; | ||
562 | xlbd_release_minors(minor, nr_minors); | ||
563 | |||
564 | blk_cleanup_queue(info->rq); | ||
565 | info->rq = NULL; | ||
566 | |||
567 | put_disk(info->gd); | ||
568 | info->gd = NULL; | ||
569 | } | ||
570 | |||
478 | static void kick_pending_request_queues(struct blkfront_info *info) | 571 | static void kick_pending_request_queues(struct blkfront_info *info) |
479 | { | 572 | { |
480 | if (!RING_FULL(&info->ring)) { | 573 | if (!RING_FULL(&info->ring)) { |
@@ -569,7 +662,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
569 | printk(KERN_WARNING "blkfront: %s: write barrier op failed\n", | 662 | printk(KERN_WARNING "blkfront: %s: write barrier op failed\n", |
570 | info->gd->disk_name); | 663 | info->gd->disk_name); |
571 | error = -EOPNOTSUPP; | 664 | error = -EOPNOTSUPP; |
572 | info->feature_barrier = 0; | 665 | info->feature_barrier = QUEUE_ORDERED_NONE; |
573 | xlvbd_barrier(info); | 666 | xlvbd_barrier(info); |
574 | } | 667 | } |
575 | /* fall through */ | 668 | /* fall through */ |
@@ -652,7 +745,7 @@ fail: | |||
652 | 745 | ||
653 | 746 | ||
654 | /* Common code used when first setting up, and when resuming. */ | 747 | /* Common code used when first setting up, and when resuming. */ |
655 | static int talk_to_backend(struct xenbus_device *dev, | 748 | static int talk_to_blkback(struct xenbus_device *dev, |
656 | struct blkfront_info *info) | 749 | struct blkfront_info *info) |
657 | { | 750 | { |
658 | const char *message = NULL; | 751 | const char *message = NULL; |
@@ -712,7 +805,6 @@ again: | |||
712 | return err; | 805 | return err; |
713 | } | 806 | } |
714 | 807 | ||
715 | |||
716 | /** | 808 | /** |
717 | * Entry point to this code when a new device is created. Allocate the basic | 809 | * Entry point to this code when a new device is created. Allocate the basic |
718 | * structures and the ring buffer for communication with the backend, and | 810 | * structures and the ring buffer for communication with the backend, and |
@@ -773,6 +865,7 @@ static int blkfront_probe(struct xenbus_device *dev, | |||
773 | return -ENOMEM; | 865 | return -ENOMEM; |
774 | } | 866 | } |
775 | 867 | ||
868 | mutex_init(&info->mutex); | ||
776 | info->xbdev = dev; | 869 | info->xbdev = dev; |
777 | info->vdevice = vdevice; | 870 | info->vdevice = vdevice; |
778 | info->connected = BLKIF_STATE_DISCONNECTED; | 871 | info->connected = BLKIF_STATE_DISCONNECTED; |
@@ -786,7 +879,7 @@ static int blkfront_probe(struct xenbus_device *dev, | |||
786 | info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); | 879 | info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); |
787 | dev_set_drvdata(&dev->dev, info); | 880 | dev_set_drvdata(&dev->dev, info); |
788 | 881 | ||
789 | err = talk_to_backend(dev, info); | 882 | err = talk_to_blkback(dev, info); |
790 | if (err) { | 883 | if (err) { |
791 | kfree(info); | 884 | kfree(info); |
792 | dev_set_drvdata(&dev->dev, NULL); | 885 | dev_set_drvdata(&dev->dev, NULL); |
@@ -881,13 +974,50 @@ static int blkfront_resume(struct xenbus_device *dev) | |||
881 | 974 | ||
882 | blkif_free(info, info->connected == BLKIF_STATE_CONNECTED); | 975 | blkif_free(info, info->connected == BLKIF_STATE_CONNECTED); |
883 | 976 | ||
884 | err = talk_to_backend(dev, info); | 977 | err = talk_to_blkback(dev, info); |
885 | if (info->connected == BLKIF_STATE_SUSPENDED && !err) | 978 | if (info->connected == BLKIF_STATE_SUSPENDED && !err) |
886 | err = blkif_recover(info); | 979 | err = blkif_recover(info); |
887 | 980 | ||
888 | return err; | 981 | return err; |
889 | } | 982 | } |
890 | 983 | ||
984 | static void | ||
985 | blkfront_closing(struct blkfront_info *info) | ||
986 | { | ||
987 | struct xenbus_device *xbdev = info->xbdev; | ||
988 | struct block_device *bdev = NULL; | ||
989 | |||
990 | mutex_lock(&info->mutex); | ||
991 | |||
992 | if (xbdev->state == XenbusStateClosing) { | ||
993 | mutex_unlock(&info->mutex); | ||
994 | return; | ||
995 | } | ||
996 | |||
997 | if (info->gd) | ||
998 | bdev = bdget_disk(info->gd, 0); | ||
999 | |||
1000 | mutex_unlock(&info->mutex); | ||
1001 | |||
1002 | if (!bdev) { | ||
1003 | xenbus_frontend_closed(xbdev); | ||
1004 | return; | ||
1005 | } | ||
1006 | |||
1007 | mutex_lock(&bdev->bd_mutex); | ||
1008 | |||
1009 | if (bdev->bd_openers) { | ||
1010 | xenbus_dev_error(xbdev, -EBUSY, | ||
1011 | "Device in use; refusing to close"); | ||
1012 | xenbus_switch_state(xbdev, XenbusStateClosing); | ||
1013 | } else { | ||
1014 | xlvbd_release_gendisk(info); | ||
1015 | xenbus_frontend_closed(xbdev); | ||
1016 | } | ||
1017 | |||
1018 | mutex_unlock(&bdev->bd_mutex); | ||
1019 | bdput(bdev); | ||
1020 | } | ||
891 | 1021 | ||
892 | /* | 1022 | /* |
893 | * Invoked when the backend is finally 'ready' (and has told produced | 1023 | * Invoked when the backend is finally 'ready' (and has told produced |
@@ -899,11 +1029,31 @@ static void blkfront_connect(struct blkfront_info *info) | |||
899 | unsigned long sector_size; | 1029 | unsigned long sector_size; |
900 | unsigned int binfo; | 1030 | unsigned int binfo; |
901 | int err; | 1031 | int err; |
902 | 1032 | int barrier; | |
903 | if ((info->connected == BLKIF_STATE_CONNECTED) || | 1033 | |
904 | (info->connected == BLKIF_STATE_SUSPENDED) ) | 1034 | switch (info->connected) { |
1035 | case BLKIF_STATE_CONNECTED: | ||
1036 | /* | ||
1037 | * Potentially, the back-end may be signalling | ||
1038 | * a capacity change; update the capacity. | ||
1039 | */ | ||
1040 | err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, | ||
1041 | "sectors", "%Lu", §ors); | ||
1042 | if (XENBUS_EXIST_ERR(err)) | ||
1043 | return; | ||
1044 | printk(KERN_INFO "Setting capacity to %Lu\n", | ||
1045 | sectors); | ||
1046 | set_capacity(info->gd, sectors); | ||
1047 | revalidate_disk(info->gd); | ||
1048 | |||
1049 | /* fall through */ | ||
1050 | case BLKIF_STATE_SUSPENDED: | ||
905 | return; | 1051 | return; |
906 | 1052 | ||
1053 | default: | ||
1054 | break; | ||
1055 | } | ||
1056 | |||
907 | dev_dbg(&info->xbdev->dev, "%s:%s.\n", | 1057 | dev_dbg(&info->xbdev->dev, "%s:%s.\n", |
908 | __func__, info->xbdev->otherend); | 1058 | __func__, info->xbdev->otherend); |
909 | 1059 | ||
@@ -920,10 +1070,26 @@ static void blkfront_connect(struct blkfront_info *info) | |||
920 | } | 1070 | } |
921 | 1071 | ||
922 | err = xenbus_gather(XBT_NIL, info->xbdev->otherend, | 1072 | err = xenbus_gather(XBT_NIL, info->xbdev->otherend, |
923 | "feature-barrier", "%lu", &info->feature_barrier, | 1073 | "feature-barrier", "%lu", &barrier, |
924 | NULL); | 1074 | NULL); |
1075 | |||
1076 | /* | ||
1077 | * If there's no "feature-barrier" defined, then it means | ||
1078 | * we're dealing with a very old backend which writes | ||
1079 | * synchronously; draining will do what needs to get done. | ||
1080 | * | ||
1081 | * If there are barriers, then we can do full queued writes | ||
1082 | * with tagged barriers. | ||
1083 | * | ||
1084 | * If barriers are not supported, then there's no much we can | ||
1085 | * do, so just set ordering to NONE. | ||
1086 | */ | ||
925 | if (err) | 1087 | if (err) |
926 | info->feature_barrier = 0; | 1088 | info->feature_barrier = QUEUE_ORDERED_DRAIN; |
1089 | else if (barrier) | ||
1090 | info->feature_barrier = QUEUE_ORDERED_TAG; | ||
1091 | else | ||
1092 | info->feature_barrier = QUEUE_ORDERED_NONE; | ||
927 | 1093 | ||
928 | err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); | 1094 | err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); |
929 | if (err) { | 1095 | if (err) { |
@@ -946,52 +1112,14 @@ static void blkfront_connect(struct blkfront_info *info) | |||
946 | } | 1112 | } |
947 | 1113 | ||
948 | /** | 1114 | /** |
949 | * Handle the change of state of the backend to Closing. We must delete our | ||
950 | * device-layer structures now, to ensure that writes are flushed through to | ||
951 | * the backend. Once is this done, we can switch to Closed in | ||
952 | * acknowledgement. | ||
953 | */ | ||
954 | static void blkfront_closing(struct xenbus_device *dev) | ||
955 | { | ||
956 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | ||
957 | unsigned long flags; | ||
958 | |||
959 | dev_dbg(&dev->dev, "blkfront_closing: %s removed\n", dev->nodename); | ||
960 | |||
961 | if (info->rq == NULL) | ||
962 | goto out; | ||
963 | |||
964 | spin_lock_irqsave(&blkif_io_lock, flags); | ||
965 | |||
966 | /* No more blkif_request(). */ | ||
967 | blk_stop_queue(info->rq); | ||
968 | |||
969 | /* No more gnttab callback work. */ | ||
970 | gnttab_cancel_free_callback(&info->callback); | ||
971 | spin_unlock_irqrestore(&blkif_io_lock, flags); | ||
972 | |||
973 | /* Flush gnttab callback work. Must be done with no locks held. */ | ||
974 | flush_scheduled_work(); | ||
975 | |||
976 | blk_cleanup_queue(info->rq); | ||
977 | info->rq = NULL; | ||
978 | |||
979 | del_gendisk(info->gd); | ||
980 | |||
981 | out: | ||
982 | xenbus_frontend_closed(dev); | ||
983 | } | ||
984 | |||
985 | /** | ||
986 | * Callback received when the backend's state changes. | 1115 | * Callback received when the backend's state changes. |
987 | */ | 1116 | */ |
988 | static void backend_changed(struct xenbus_device *dev, | 1117 | static void blkback_changed(struct xenbus_device *dev, |
989 | enum xenbus_state backend_state) | 1118 | enum xenbus_state backend_state) |
990 | { | 1119 | { |
991 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | 1120 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); |
992 | struct block_device *bd; | ||
993 | 1121 | ||
994 | dev_dbg(&dev->dev, "blkfront:backend_changed.\n"); | 1122 | dev_dbg(&dev->dev, "blkfront:blkback_changed to state %d.\n", backend_state); |
995 | 1123 | ||
996 | switch (backend_state) { | 1124 | switch (backend_state) { |
997 | case XenbusStateInitialising: | 1125 | case XenbusStateInitialising: |
@@ -1006,35 +1134,56 @@ static void backend_changed(struct xenbus_device *dev, | |||
1006 | break; | 1134 | break; |
1007 | 1135 | ||
1008 | case XenbusStateClosing: | 1136 | case XenbusStateClosing: |
1009 | if (info->gd == NULL) { | 1137 | blkfront_closing(info); |
1010 | xenbus_frontend_closed(dev); | ||
1011 | break; | ||
1012 | } | ||
1013 | bd = bdget_disk(info->gd, 0); | ||
1014 | if (bd == NULL) | ||
1015 | xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); | ||
1016 | |||
1017 | mutex_lock(&bd->bd_mutex); | ||
1018 | if (info->users > 0) | ||
1019 | xenbus_dev_error(dev, -EBUSY, | ||
1020 | "Device in use; refusing to close"); | ||
1021 | else | ||
1022 | blkfront_closing(dev); | ||
1023 | mutex_unlock(&bd->bd_mutex); | ||
1024 | bdput(bd); | ||
1025 | break; | 1138 | break; |
1026 | } | 1139 | } |
1027 | } | 1140 | } |
1028 | 1141 | ||
1029 | static int blkfront_remove(struct xenbus_device *dev) | 1142 | static int blkfront_remove(struct xenbus_device *xbdev) |
1030 | { | 1143 | { |
1031 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | 1144 | struct blkfront_info *info = dev_get_drvdata(&xbdev->dev); |
1145 | struct block_device *bdev = NULL; | ||
1146 | struct gendisk *disk; | ||
1032 | 1147 | ||
1033 | dev_dbg(&dev->dev, "blkfront_remove: %s removed\n", dev->nodename); | 1148 | dev_dbg(&xbdev->dev, "%s removed", xbdev->nodename); |
1034 | 1149 | ||
1035 | blkif_free(info, 0); | 1150 | blkif_free(info, 0); |
1036 | 1151 | ||
1037 | kfree(info); | 1152 | mutex_lock(&info->mutex); |
1153 | |||
1154 | disk = info->gd; | ||
1155 | if (disk) | ||
1156 | bdev = bdget_disk(disk, 0); | ||
1157 | |||
1158 | info->xbdev = NULL; | ||
1159 | mutex_unlock(&info->mutex); | ||
1160 | |||
1161 | if (!bdev) { | ||
1162 | kfree(info); | ||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | /* | ||
1167 | * The xbdev was removed before we reached the Closed | ||
1168 | * state. See if it's safe to remove the disk. If the bdev | ||
1169 | * isn't closed yet, we let release take care of it. | ||
1170 | */ | ||
1171 | |||
1172 | mutex_lock(&bdev->bd_mutex); | ||
1173 | info = disk->private_data; | ||
1174 | |||
1175 | dev_warn(disk_to_dev(disk), | ||
1176 | "%s was hot-unplugged, %d stale handles\n", | ||
1177 | xbdev->nodename, bdev->bd_openers); | ||
1178 | |||
1179 | if (info && !bdev->bd_openers) { | ||
1180 | xlvbd_release_gendisk(info); | ||
1181 | disk->private_data = NULL; | ||
1182 | kfree(info); | ||
1183 | } | ||
1184 | |||
1185 | mutex_unlock(&bdev->bd_mutex); | ||
1186 | bdput(bdev); | ||
1038 | 1187 | ||
1039 | return 0; | 1188 | return 0; |
1040 | } | 1189 | } |
@@ -1043,30 +1192,78 @@ static int blkfront_is_ready(struct xenbus_device *dev) | |||
1043 | { | 1192 | { |
1044 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); | 1193 | struct blkfront_info *info = dev_get_drvdata(&dev->dev); |
1045 | 1194 | ||
1046 | return info->is_ready; | 1195 | return info->is_ready && info->xbdev; |
1047 | } | 1196 | } |
1048 | 1197 | ||
1049 | static int blkif_open(struct block_device *bdev, fmode_t mode) | 1198 | static int blkif_open(struct block_device *bdev, fmode_t mode) |
1050 | { | 1199 | { |
1051 | struct blkfront_info *info = bdev->bd_disk->private_data; | 1200 | struct gendisk *disk = bdev->bd_disk; |
1052 | info->users++; | 1201 | struct blkfront_info *info; |
1053 | return 0; | 1202 | int err = 0; |
1203 | |||
1204 | lock_kernel(); | ||
1205 | |||
1206 | info = disk->private_data; | ||
1207 | if (!info) { | ||
1208 | /* xbdev gone */ | ||
1209 | err = -ERESTARTSYS; | ||
1210 | goto out; | ||
1211 | } | ||
1212 | |||
1213 | mutex_lock(&info->mutex); | ||
1214 | |||
1215 | if (!info->gd) | ||
1216 | /* xbdev is closed */ | ||
1217 | err = -ERESTARTSYS; | ||
1218 | |||
1219 | mutex_unlock(&info->mutex); | ||
1220 | |||
1221 | out: | ||
1222 | unlock_kernel(); | ||
1223 | return err; | ||
1054 | } | 1224 | } |
1055 | 1225 | ||
1056 | static int blkif_release(struct gendisk *disk, fmode_t mode) | 1226 | static int blkif_release(struct gendisk *disk, fmode_t mode) |
1057 | { | 1227 | { |
1058 | struct blkfront_info *info = disk->private_data; | 1228 | struct blkfront_info *info = disk->private_data; |
1059 | info->users--; | 1229 | struct block_device *bdev; |
1060 | if (info->users == 0) { | 1230 | struct xenbus_device *xbdev; |
1061 | /* Check whether we have been instructed to close. We will | 1231 | |
1062 | have ignored this request initially, as the device was | 1232 | lock_kernel(); |
1063 | still mounted. */ | 1233 | |
1064 | struct xenbus_device *dev = info->xbdev; | 1234 | bdev = bdget_disk(disk, 0); |
1065 | enum xenbus_state state = xenbus_read_driver_state(dev->otherend); | 1235 | bdput(bdev); |
1066 | 1236 | ||
1067 | if (state == XenbusStateClosing && info->is_ready) | 1237 | if (bdev->bd_openers) |
1068 | blkfront_closing(dev); | 1238 | goto out; |
1239 | |||
1240 | /* | ||
1241 | * Check if we have been instructed to close. We will have | ||
1242 | * deferred this request, because the bdev was still open. | ||
1243 | */ | ||
1244 | |||
1245 | mutex_lock(&info->mutex); | ||
1246 | xbdev = info->xbdev; | ||
1247 | |||
1248 | if (xbdev && xbdev->state == XenbusStateClosing) { | ||
1249 | /* pending switch to state closed */ | ||
1250 | dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n"); | ||
1251 | xlvbd_release_gendisk(info); | ||
1252 | xenbus_frontend_closed(info->xbdev); | ||
1253 | } | ||
1254 | |||
1255 | mutex_unlock(&info->mutex); | ||
1256 | |||
1257 | if (!xbdev) { | ||
1258 | /* sudden device removal */ | ||
1259 | dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n"); | ||
1260 | xlvbd_release_gendisk(info); | ||
1261 | disk->private_data = NULL; | ||
1262 | kfree(info); | ||
1069 | } | 1263 | } |
1264 | |||
1265 | out: | ||
1266 | unlock_kernel(); | ||
1070 | return 0; | 1267 | return 0; |
1071 | } | 1268 | } |
1072 | 1269 | ||
@@ -1076,7 +1273,7 @@ static const struct block_device_operations xlvbd_block_fops = | |||
1076 | .open = blkif_open, | 1273 | .open = blkif_open, |
1077 | .release = blkif_release, | 1274 | .release = blkif_release, |
1078 | .getgeo = blkif_getgeo, | 1275 | .getgeo = blkif_getgeo, |
1079 | .locked_ioctl = blkif_ioctl, | 1276 | .ioctl = blkif_ioctl, |
1080 | }; | 1277 | }; |
1081 | 1278 | ||
1082 | 1279 | ||
@@ -1092,7 +1289,7 @@ static struct xenbus_driver blkfront = { | |||
1092 | .probe = blkfront_probe, | 1289 | .probe = blkfront_probe, |
1093 | .remove = blkfront_remove, | 1290 | .remove = blkfront_remove, |
1094 | .resume = blkfront_resume, | 1291 | .resume = blkfront_resume, |
1095 | .otherend_changed = backend_changed, | 1292 | .otherend_changed = blkback_changed, |
1096 | .is_ready = blkfront_is_ready, | 1293 | .is_ready = blkfront_is_ready, |
1097 | }; | 1294 | }; |
1098 | 1295 | ||