aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/xen-blkfront.c41
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 {
68struct grant { 68struct 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
74struct blk_shadow { 74struct 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
791static void blkif_free(struct blkfront_info *info, int suspend) 792static 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);