diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/xen-blkfront.c | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 962064487ef7..97324cd18f4b 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | #include <linux/scatterlist.h> | 45 | #include <linux/scatterlist.h> |
46 | #include <linux/bitmap.h> | 46 | #include <linux/bitmap.h> |
47 | #include <linux/llist.h> | 47 | #include <linux/list.h> |
48 | 48 | ||
49 | #include <xen/xen.h> | 49 | #include <xen/xen.h> |
50 | #include <xen/xenbus.h> | 50 | #include <xen/xenbus.h> |
@@ -68,7 +68,7 @@ enum blkif_state { | |||
68 | struct grant { | 68 | struct grant { |
69 | grant_ref_t gref; | 69 | grant_ref_t gref; |
70 | unsigned long pfn; | 70 | unsigned long pfn; |
71 | struct llist_node node; | 71 | struct list_head node; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct blk_shadow { | 74 | struct blk_shadow { |
@@ -105,7 +105,7 @@ struct blkfront_info | |||
105 | struct work_struct work; | 105 | struct work_struct work; |
106 | struct gnttab_free_callback callback; | 106 | struct gnttab_free_callback callback; |
107 | struct blk_shadow shadow[BLK_RING_SIZE]; | 107 | struct blk_shadow shadow[BLK_RING_SIZE]; |
108 | struct llist_head persistent_gnts; | 108 | struct list_head persistent_gnts; |
109 | unsigned int persistent_gnts_c; | 109 | unsigned int persistent_gnts_c; |
110 | unsigned long shadow_free; | 110 | unsigned long shadow_free; |
111 | unsigned int feature_flush; | 111 | unsigned int feature_flush; |
@@ -371,10 +371,11 @@ static int blkif_queue_request(struct request *req) | |||
371 | lsect = fsect + (sg->length >> 9) - 1; | 371 | lsect = fsect + (sg->length >> 9) - 1; |
372 | 372 | ||
373 | if (info->persistent_gnts_c) { | 373 | if (info->persistent_gnts_c) { |
374 | BUG_ON(llist_empty(&info->persistent_gnts)); | 374 | BUG_ON(list_empty(&info->persistent_gnts)); |
375 | gnt_list_entry = llist_entry( | 375 | gnt_list_entry = list_first_entry( |
376 | llist_del_first(&info->persistent_gnts), | 376 | &info->persistent_gnts, |
377 | struct grant, node); | 377 | struct grant, node); |
378 | list_del(&gnt_list_entry->node); | ||
378 | 379 | ||
379 | ref = gnt_list_entry->gref; | 380 | ref = gnt_list_entry->gref; |
380 | buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); | 381 | buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); |
@@ -790,9 +791,8 @@ static void blkif_restart_queue(struct work_struct *work) | |||
790 | 791 | ||
791 | static void blkif_free(struct blkfront_info *info, int suspend) | 792 | static void blkif_free(struct blkfront_info *info, int suspend) |
792 | { | 793 | { |
793 | struct llist_node *all_gnts; | 794 | struct grant *persistent_gnt; |
794 | struct grant *persistent_gnt, *tmp; | 795 | struct grant *n; |
795 | struct llist_node *n; | ||
796 | 796 | ||
797 | /* Prevent new requests being issued until we fix things up. */ | 797 | /* Prevent new requests being issued until we fix things up. */ |
798 | spin_lock_irq(&info->io_lock); | 798 | spin_lock_irq(&info->io_lock); |
@@ -804,20 +804,15 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
804 | 804 | ||
805 | /* Remove all persistent grants */ | 805 | /* Remove all persistent grants */ |
806 | if (info->persistent_gnts_c) { | 806 | if (info->persistent_gnts_c) { |
807 | all_gnts = llist_del_all(&info->persistent_gnts); | 807 | list_for_each_entry_safe(persistent_gnt, n, |
808 | persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node); | 808 | &info->persistent_gnts, node) { |
809 | while (persistent_gnt) { | 809 | list_del(&persistent_gnt->node); |
810 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); | 810 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); |
811 | __free_page(pfn_to_page(persistent_gnt->pfn)); | 811 | __free_page(pfn_to_page(persistent_gnt->pfn)); |
812 | tmp = persistent_gnt; | 812 | kfree(persistent_gnt); |
813 | n = persistent_gnt->node.next; | 813 | info->persistent_gnts_c--; |
814 | if (n) | ||
815 | persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node); | ||
816 | else | ||
817 | persistent_gnt = NULL; | ||
818 | kfree(tmp); | ||
819 | } | 814 | } |
820 | info->persistent_gnts_c = 0; | 815 | BUG_ON(info->persistent_gnts_c != 0); |
821 | } | 816 | } |
822 | 817 | ||
823 | /* No more gnttab callback work. */ | 818 | /* No more gnttab callback work. */ |
@@ -875,7 +870,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
875 | } | 870 | } |
876 | /* Add the persistent grant into the list of free grants */ | 871 | /* Add the persistent grant into the list of free grants */ |
877 | for (i = 0; i < s->req.u.rw.nr_segments; i++) { | 872 | for (i = 0; i < s->req.u.rw.nr_segments; i++) { |
878 | llist_add(&s->grants_used[i]->node, &info->persistent_gnts); | 873 | list_add(&s->grants_used[i]->node, &info->persistent_gnts); |
879 | info->persistent_gnts_c++; | 874 | info->persistent_gnts_c++; |
880 | } | 875 | } |
881 | } | 876 | } |
@@ -1171,7 +1166,7 @@ static int blkfront_probe(struct xenbus_device *dev, | |||
1171 | spin_lock_init(&info->io_lock); | 1166 | spin_lock_init(&info->io_lock); |
1172 | info->xbdev = dev; | 1167 | info->xbdev = dev; |
1173 | info->vdevice = vdevice; | 1168 | info->vdevice = vdevice; |
1174 | init_llist_head(&info->persistent_gnts); | 1169 | INIT_LIST_HEAD(&info->persistent_gnts); |
1175 | info->persistent_gnts_c = 0; | 1170 | info->persistent_gnts_c = 0; |
1176 | info->connected = BLKIF_STATE_DISCONNECTED; | 1171 | info->connected = BLKIF_STATE_DISCONNECTED; |
1177 | INIT_WORK(&info->work, blkif_restart_queue); | 1172 | INIT_WORK(&info->work, blkif_restart_queue); |