diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 1 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_state.c | 7 | ||||
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 24 | ||||
-rw-r--r-- | drivers/block/virtio_blk.c | 7 | ||||
-rw-r--r-- | drivers/block/xen-blkback/blkback.c | 25 | ||||
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 49 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 21 |
8 files changed, 87 insertions, 49 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index f58a4a4b4dfb..2b8303ad63c9 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -168,7 +168,7 @@ static void wake_all_senders(struct drbd_tconn *tconn) { | |||
168 | } | 168 | } |
169 | 169 | ||
170 | /* must hold resource->req_lock */ | 170 | /* must hold resource->req_lock */ |
171 | static void start_new_tl_epoch(struct drbd_tconn *tconn) | 171 | void start_new_tl_epoch(struct drbd_tconn *tconn) |
172 | { | 172 | { |
173 | /* no point closing an epoch, if it is empty, anyways. */ | 173 | /* no point closing an epoch, if it is empty, anyways. */ |
174 | if (tconn->current_tle_writes == 0) | 174 | if (tconn->current_tle_writes == 0) |
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 016de6b8bb57..c08d22964d06 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -267,6 +267,7 @@ struct bio_and_error { | |||
267 | int error; | 267 | int error; |
268 | }; | 268 | }; |
269 | 269 | ||
270 | extern void start_new_tl_epoch(struct drbd_tconn *tconn); | ||
270 | extern void drbd_req_destroy(struct kref *kref); | 271 | extern void drbd_req_destroy(struct kref *kref); |
271 | extern void _req_may_be_done(struct drbd_request *req, | 272 | extern void _req_may_be_done(struct drbd_request *req, |
272 | struct bio_and_error *m); | 273 | struct bio_and_error *m); |
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 53bf6182bac4..0fe220cfb9e9 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -931,6 +931,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
931 | enum drbd_state_rv rv = SS_SUCCESS; | 931 | enum drbd_state_rv rv = SS_SUCCESS; |
932 | enum sanitize_state_warnings ssw; | 932 | enum sanitize_state_warnings ssw; |
933 | struct after_state_chg_work *ascw; | 933 | struct after_state_chg_work *ascw; |
934 | bool did_remote, should_do_remote; | ||
934 | 935 | ||
935 | os = drbd_read_state(mdev); | 936 | os = drbd_read_state(mdev); |
936 | 937 | ||
@@ -981,11 +982,17 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
981 | (os.disk != D_DISKLESS && ns.disk == D_DISKLESS)) | 982 | (os.disk != D_DISKLESS && ns.disk == D_DISKLESS)) |
982 | atomic_inc(&mdev->local_cnt); | 983 | atomic_inc(&mdev->local_cnt); |
983 | 984 | ||
985 | did_remote = drbd_should_do_remote(mdev->state); | ||
984 | mdev->state.i = ns.i; | 986 | mdev->state.i = ns.i; |
987 | should_do_remote = drbd_should_do_remote(mdev->state); | ||
985 | mdev->tconn->susp = ns.susp; | 988 | mdev->tconn->susp = ns.susp; |
986 | mdev->tconn->susp_nod = ns.susp_nod; | 989 | mdev->tconn->susp_nod = ns.susp_nod; |
987 | mdev->tconn->susp_fen = ns.susp_fen; | 990 | mdev->tconn->susp_fen = ns.susp_fen; |
988 | 991 | ||
992 | /* put replicated vs not-replicated requests in seperate epochs */ | ||
993 | if (did_remote != should_do_remote) | ||
994 | start_new_tl_epoch(mdev->tconn); | ||
995 | |||
989 | if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING) | 996 | if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING) |
990 | drbd_print_uuids(mdev, "attached to UUIDs"); | 997 | drbd_print_uuids(mdev, "attached to UUIDs"); |
991 | 998 | ||
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 9790666f90f2..11cc9522cdd4 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -629,12 +629,13 @@ static void mtip_timeout_function(unsigned long int data) | |||
629 | } | 629 | } |
630 | } | 630 | } |
631 | 631 | ||
632 | if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { | 632 | if (cmdto_cnt) { |
633 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); | 633 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); |
634 | 634 | if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { | |
635 | mtip_restart_port(port); | 635 | mtip_restart_port(port); |
636 | wake_up_interruptible(&port->svc_wait); | ||
637 | } | ||
636 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); | 638 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); |
637 | wake_up_interruptible(&port->svc_wait); | ||
638 | } | 639 | } |
639 | 640 | ||
640 | if (port->ic_pause_timer) { | 641 | if (port->ic_pause_timer) { |
@@ -4017,7 +4018,12 @@ static int mtip_block_remove(struct driver_data *dd) | |||
4017 | * Delete our gendisk structure. This also removes the device | 4018 | * Delete our gendisk structure. This also removes the device |
4018 | * from /dev | 4019 | * from /dev |
4019 | */ | 4020 | */ |
4020 | del_gendisk(dd->disk); | 4021 | if (dd->disk) { |
4022 | if (dd->disk->queue) | ||
4023 | del_gendisk(dd->disk); | ||
4024 | else | ||
4025 | put_disk(dd->disk); | ||
4026 | } | ||
4021 | 4027 | ||
4022 | spin_lock(&rssd_index_lock); | 4028 | spin_lock(&rssd_index_lock); |
4023 | ida_remove(&rssd_index_ida, dd->index); | 4029 | ida_remove(&rssd_index_ida, dd->index); |
@@ -4051,7 +4057,13 @@ static int mtip_block_shutdown(struct driver_data *dd) | |||
4051 | "Shutting down %s ...\n", dd->disk->disk_name); | 4057 | "Shutting down %s ...\n", dd->disk->disk_name); |
4052 | 4058 | ||
4053 | /* Delete our gendisk structure, and cleanup the blk queue. */ | 4059 | /* Delete our gendisk structure, and cleanup the blk queue. */ |
4054 | del_gendisk(dd->disk); | 4060 | if (dd->disk) { |
4061 | if (dd->disk->queue) | ||
4062 | del_gendisk(dd->disk); | ||
4063 | else | ||
4064 | put_disk(dd->disk); | ||
4065 | } | ||
4066 | |||
4055 | 4067 | ||
4056 | spin_lock(&rssd_index_lock); | 4068 | spin_lock(&rssd_index_lock); |
4057 | ida_remove(&rssd_index_ida, dd->index); | 4069 | ida_remove(&rssd_index_ida, dd->index); |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9d8409c02082..8ad21a25bc0d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
889 | { | 889 | { |
890 | struct virtio_blk *vblk = vdev->priv; | 890 | struct virtio_blk *vblk = vdev->priv; |
891 | int index = vblk->index; | 891 | int index = vblk->index; |
892 | int refc; | ||
892 | 893 | ||
893 | /* Prevent config work handler from accessing the device. */ | 894 | /* Prevent config work handler from accessing the device. */ |
894 | mutex_lock(&vblk->config_lock); | 895 | mutex_lock(&vblk->config_lock); |
@@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
903 | 904 | ||
904 | flush_work(&vblk->config_work); | 905 | flush_work(&vblk->config_work); |
905 | 906 | ||
907 | refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); | ||
906 | put_disk(vblk->disk); | 908 | put_disk(vblk->disk); |
907 | mempool_destroy(vblk->pool); | 909 | mempool_destroy(vblk->pool); |
908 | vdev->config->del_vqs(vdev); | 910 | vdev->config->del_vqs(vdev); |
909 | kfree(vblk); | 911 | kfree(vblk); |
910 | ida_simple_remove(&vd_index_ida, index); | 912 | |
913 | /* Only free device id if we don't have any users */ | ||
914 | if (refc == 1) | ||
915 | ida_simple_remove(&vd_index_ida, index); | ||
911 | } | 916 | } |
912 | 917 | ||
913 | #ifdef CONFIG_PM | 918 | #ifdef CONFIG_PM |
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 74374fb762aa..de1f319f7bd7 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <xen/xen.h> | 46 | #include <xen/xen.h> |
47 | #include <asm/xen/hypervisor.h> | 47 | #include <asm/xen/hypervisor.h> |
48 | #include <asm/xen/hypercall.h> | 48 | #include <asm/xen/hypercall.h> |
49 | #include <xen/balloon.h> | ||
49 | #include "common.h" | 50 | #include "common.h" |
50 | 51 | ||
51 | /* | 52 | /* |
@@ -161,10 +162,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
161 | static void make_response(struct xen_blkif *blkif, u64 id, | 162 | static void make_response(struct xen_blkif *blkif, u64 id, |
162 | unsigned short op, int st); | 163 | unsigned short op, int st); |
163 | 164 | ||
164 | #define foreach_grant(pos, rbtree, node) \ | 165 | #define foreach_grant_safe(pos, n, rbtree, node) \ |
165 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \ | 166 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ |
167 | (n) = rb_next(&(pos)->node); \ | ||
166 | &(pos)->node != NULL; \ | 168 | &(pos)->node != NULL; \ |
167 | (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node)) | 169 | (pos) = container_of(n, typeof(*(pos)), node), \ |
170 | (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL) | ||
168 | 171 | ||
169 | 172 | ||
170 | static void add_persistent_gnt(struct rb_root *root, | 173 | static void add_persistent_gnt(struct rb_root *root, |
@@ -217,10 +220,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) | |||
217 | struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 220 | struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
218 | struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 221 | struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
219 | struct persistent_gnt *persistent_gnt; | 222 | struct persistent_gnt *persistent_gnt; |
223 | struct rb_node *n; | ||
220 | int ret = 0; | 224 | int ret = 0; |
221 | int segs_to_unmap = 0; | 225 | int segs_to_unmap = 0; |
222 | 226 | ||
223 | foreach_grant(persistent_gnt, root, node) { | 227 | foreach_grant_safe(persistent_gnt, n, root, node) { |
224 | BUG_ON(persistent_gnt->handle == | 228 | BUG_ON(persistent_gnt->handle == |
225 | BLKBACK_INVALID_HANDLE); | 229 | BLKBACK_INVALID_HANDLE); |
226 | gnttab_set_unmap_op(&unmap[segs_to_unmap], | 230 | gnttab_set_unmap_op(&unmap[segs_to_unmap], |
@@ -230,17 +234,19 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) | |||
230 | persistent_gnt->handle); | 234 | persistent_gnt->handle); |
231 | 235 | ||
232 | pages[segs_to_unmap] = persistent_gnt->page; | 236 | pages[segs_to_unmap] = persistent_gnt->page; |
233 | rb_erase(&persistent_gnt->node, root); | ||
234 | kfree(persistent_gnt); | ||
235 | num--; | ||
236 | 237 | ||
237 | if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || | 238 | if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || |
238 | !rb_next(&persistent_gnt->node)) { | 239 | !rb_next(&persistent_gnt->node)) { |
239 | ret = gnttab_unmap_refs(unmap, NULL, pages, | 240 | ret = gnttab_unmap_refs(unmap, NULL, pages, |
240 | segs_to_unmap); | 241 | segs_to_unmap); |
241 | BUG_ON(ret); | 242 | BUG_ON(ret); |
243 | free_xenballooned_pages(segs_to_unmap, pages); | ||
242 | segs_to_unmap = 0; | 244 | segs_to_unmap = 0; |
243 | } | 245 | } |
246 | |||
247 | rb_erase(&persistent_gnt->node, root); | ||
248 | kfree(persistent_gnt); | ||
249 | num--; | ||
244 | } | 250 | } |
245 | BUG_ON(num != 0); | 251 | BUG_ON(num != 0); |
246 | } | 252 | } |
@@ -523,8 +529,8 @@ static int xen_blkbk_map(struct blkif_request *req, | |||
523 | GFP_KERNEL); | 529 | GFP_KERNEL); |
524 | if (!persistent_gnt) | 530 | if (!persistent_gnt) |
525 | return -ENOMEM; | 531 | return -ENOMEM; |
526 | persistent_gnt->page = alloc_page(GFP_KERNEL); | 532 | if (alloc_xenballooned_pages(1, &persistent_gnt->page, |
527 | if (!persistent_gnt->page) { | 533 | false)) { |
528 | kfree(persistent_gnt); | 534 | kfree(persistent_gnt); |
529 | return -ENOMEM; | 535 | return -ENOMEM; |
530 | } | 536 | } |
@@ -875,7 +881,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
875 | goto fail_response; | 881 | goto fail_response; |
876 | } | 882 | } |
877 | 883 | ||
878 | preq.dev = req->u.rw.handle; | ||
879 | preq.sector_number = req->u.rw.sector_number; | 884 | preq.sector_number = req->u.rw.sector_number; |
880 | preq.nr_sects = 0; | 885 | preq.nr_sects = 0; |
881 | 886 | ||
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 63980722db41..5e237f630c47 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev) | |||
367 | be->blkif = NULL; | 367 | be->blkif = NULL; |
368 | } | 368 | } |
369 | 369 | ||
370 | kfree(be->mode); | ||
370 | kfree(be); | 371 | kfree(be); |
371 | dev_set_drvdata(&dev->dev, NULL); | 372 | dev_set_drvdata(&dev->dev, NULL); |
372 | return 0; | 373 | return 0; |
@@ -502,6 +503,7 @@ static void backend_changed(struct xenbus_watch *watch, | |||
502 | = container_of(watch, struct backend_info, backend_watch); | 503 | = container_of(watch, struct backend_info, backend_watch); |
503 | struct xenbus_device *dev = be->dev; | 504 | struct xenbus_device *dev = be->dev; |
504 | int cdrom = 0; | 505 | int cdrom = 0; |
506 | unsigned long handle; | ||
505 | char *device_type; | 507 | char *device_type; |
506 | 508 | ||
507 | DPRINTK(""); | 509 | DPRINTK(""); |
@@ -521,10 +523,10 @@ static void backend_changed(struct xenbus_watch *watch, | |||
521 | return; | 523 | return; |
522 | } | 524 | } |
523 | 525 | ||
524 | if ((be->major || be->minor) && | 526 | if (be->major | be->minor) { |
525 | ((be->major != major) || (be->minor != minor))) { | 527 | if (be->major != major || be->minor != minor) |
526 | pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", | 528 | pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", |
527 | be->major, be->minor, major, minor); | 529 | be->major, be->minor, major, minor); |
528 | return; | 530 | return; |
529 | } | 531 | } |
530 | 532 | ||
@@ -542,36 +544,33 @@ static void backend_changed(struct xenbus_watch *watch, | |||
542 | kfree(device_type); | 544 | kfree(device_type); |
543 | } | 545 | } |
544 | 546 | ||
545 | if (be->major == 0 && be->minor == 0) { | 547 | /* Front end dir is a number, which is used as the handle. */ |
546 | /* Front end dir is a number, which is used as the handle. */ | 548 | err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle); |
547 | 549 | if (err) | |
548 | char *p = strrchr(dev->otherend, '/') + 1; | 550 | return; |
549 | long handle; | ||
550 | err = strict_strtoul(p, 0, &handle); | ||
551 | if (err) | ||
552 | return; | ||
553 | 551 | ||
554 | be->major = major; | 552 | be->major = major; |
555 | be->minor = minor; | 553 | be->minor = minor; |
556 | 554 | ||
557 | err = xen_vbd_create(be->blkif, handle, major, minor, | 555 | err = xen_vbd_create(be->blkif, handle, major, minor, |
558 | (NULL == strchr(be->mode, 'w')), cdrom); | 556 | !strchr(be->mode, 'w'), cdrom); |
559 | if (err) { | ||
560 | be->major = 0; | ||
561 | be->minor = 0; | ||
562 | xenbus_dev_fatal(dev, err, "creating vbd structure"); | ||
563 | return; | ||
564 | } | ||
565 | 557 | ||
558 | if (err) | ||
559 | xenbus_dev_fatal(dev, err, "creating vbd structure"); | ||
560 | else { | ||
566 | err = xenvbd_sysfs_addif(dev); | 561 | err = xenvbd_sysfs_addif(dev); |
567 | if (err) { | 562 | if (err) { |
568 | xen_vbd_free(&be->blkif->vbd); | 563 | xen_vbd_free(&be->blkif->vbd); |
569 | be->major = 0; | ||
570 | be->minor = 0; | ||
571 | xenbus_dev_fatal(dev, err, "creating sysfs entries"); | 564 | xenbus_dev_fatal(dev, err, "creating sysfs entries"); |
572 | return; | ||
573 | } | 565 | } |
566 | } | ||
574 | 567 | ||
568 | if (err) { | ||
569 | kfree(be->mode); | ||
570 | be->mode = NULL; | ||
571 | be->major = 0; | ||
572 | be->minor = 0; | ||
573 | } else { | ||
575 | /* We're potentially connected now */ | 574 | /* We're potentially connected now */ |
576 | xen_update_blkif_status(be->blkif); | 575 | xen_update_blkif_status(be->blkif); |
577 | } | 576 | } |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 96e9b00db081..c3dae2e0f290 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -791,7 +791,8 @@ static void blkif_restart_queue(struct work_struct *work) | |||
791 | static void blkif_free(struct blkfront_info *info, int suspend) | 791 | static void blkif_free(struct blkfront_info *info, int suspend) |
792 | { | 792 | { |
793 | struct llist_node *all_gnts; | 793 | struct llist_node *all_gnts; |
794 | struct grant *persistent_gnt; | 794 | struct grant *persistent_gnt, *tmp; |
795 | struct llist_node *n; | ||
795 | 796 | ||
796 | /* Prevent new requests being issued until we fix things up. */ | 797 | /* Prevent new requests being issued until we fix things up. */ |
797 | spin_lock_irq(&info->io_lock); | 798 | spin_lock_irq(&info->io_lock); |
@@ -804,10 +805,17 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
804 | /* Remove all persistent grants */ | 805 | /* Remove all persistent grants */ |
805 | if (info->persistent_gnts_c) { | 806 | if (info->persistent_gnts_c) { |
806 | all_gnts = llist_del_all(&info->persistent_gnts); | 807 | all_gnts = llist_del_all(&info->persistent_gnts); |
807 | llist_for_each_entry(persistent_gnt, all_gnts, node) { | 808 | persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node); |
809 | while (persistent_gnt) { | ||
808 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); | 810 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); |
809 | __free_page(pfn_to_page(persistent_gnt->pfn)); | 811 | __free_page(pfn_to_page(persistent_gnt->pfn)); |
810 | kfree(persistent_gnt); | 812 | tmp = persistent_gnt; |
813 | n = persistent_gnt->node.next; | ||
814 | if (n) | ||
815 | persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node); | ||
816 | else | ||
817 | persistent_gnt = NULL; | ||
818 | kfree(tmp); | ||
811 | } | 819 | } |
812 | info->persistent_gnts_c = 0; | 820 | info->persistent_gnts_c = 0; |
813 | } | 821 | } |
@@ -835,7 +843,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
835 | static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | 843 | static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, |
836 | struct blkif_response *bret) | 844 | struct blkif_response *bret) |
837 | { | 845 | { |
838 | int i; | 846 | int i = 0; |
839 | struct bio_vec *bvec; | 847 | struct bio_vec *bvec; |
840 | struct req_iterator iter; | 848 | struct req_iterator iter; |
841 | unsigned long flags; | 849 | unsigned long flags; |
@@ -852,7 +860,8 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
852 | */ | 860 | */ |
853 | rq_for_each_segment(bvec, s->request, iter) { | 861 | rq_for_each_segment(bvec, s->request, iter) { |
854 | BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE); | 862 | BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE); |
855 | i = offset >> PAGE_SHIFT; | 863 | if (bvec->bv_offset < offset) |
864 | i++; | ||
856 | BUG_ON(i >= s->req.u.rw.nr_segments); | 865 | BUG_ON(i >= s->req.u.rw.nr_segments); |
857 | shared_data = kmap_atomic( | 866 | shared_data = kmap_atomic( |
858 | pfn_to_page(s->grants_used[i]->pfn)); | 867 | pfn_to_page(s->grants_used[i]->pfn)); |
@@ -861,7 +870,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
861 | bvec->bv_len); | 870 | bvec->bv_len); |
862 | bvec_kunmap_irq(bvec_data, &flags); | 871 | bvec_kunmap_irq(bvec_data, &flags); |
863 | kunmap_atomic(shared_data); | 872 | kunmap_atomic(shared_data); |
864 | offset += bvec->bv_len; | 873 | offset = bvec->bv_offset + bvec->bv_len; |
865 | } | 874 | } |
866 | } | 875 | } |
867 | /* Add the persistent grant into the list of free grants */ | 876 | /* Add the persistent grant into the list of free grants */ |