diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-08 14:46:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-08 14:46:48 -0400 |
commit | 752240e74d650faa24425adc523f1308973ea51c (patch) | |
tree | 47657b7d468352424f844156883302653252f70e /drivers/block/xen-blkfront.c | |
parent | b8cb642af98216fe6eeca1525345b8a5c9d7c9a4 (diff) | |
parent | 626d7508664c4bc8e67f496da4387ecd0c410b8c (diff) |
Merge tag 'for-linus-4.3-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from David Vrabel:
"Xen features and fixes for 4.3:
- Convert xen-blkfront to the multiqueue API
- [arm] Support binding event channels to different VCPUs.
- [x86] Support > 512 GiB in a PV guests (off by default as such a
guest cannot be migrated with the current toolstack).
- [x86] PMU support for PV dom0 (limited support for using perf with
Xen and other guests)"
* tag 'for-linus-4.3-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: (33 commits)
xen: switch extra memory accounting to use pfns
xen: limit memory to architectural maximum
xen: avoid another early crash of memory limited dom0
xen: avoid early crash of memory limited dom0
arm/xen: Remove helpers which are PV specific
xen/x86: Don't try to set PCE bit in CR4
xen/PMU: PMU emulation code
xen/PMU: Intercept PMU-related MSR and APIC accesses
xen/PMU: Describe vendor-specific PMU registers
xen/PMU: Initialization code for Xen PMU
xen/PMU: Sysfs interface for setting Xen PMU mode
xen: xensyms support
xen: remove no longer needed p2m.h
xen: allow more than 512 GB of RAM for 64 bit pv-domains
xen: move p2m list if conflicting with e820 map
xen: add explicit memblock_reserve() calls for special pages
mm: provide early_memremap_ro to establish read-only mapping
xen: check for initrd conflicting with e820 map
xen: check pre-allocated page tables for conflict with memory map
xen: check for kernel memory conflicting with memory layout
...
Diffstat (limited to 'drivers/block/xen-blkfront.c')
-rw-r--r-- | drivers/block/xen-blkfront.c | 146 |
1 files changed, 60 insertions, 86 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 5f6b3be0a93c..15083539df15 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
40 | #include <linux/blk-mq.h> | ||
40 | #include <linux/hdreg.h> | 41 | #include <linux/hdreg.h> |
41 | #include <linux/cdrom.h> | 42 | #include <linux/cdrom.h> |
42 | #include <linux/module.h> | 43 | #include <linux/module.h> |
@@ -147,6 +148,7 @@ struct blkfront_info | |||
147 | unsigned int feature_persistent:1; | 148 | unsigned int feature_persistent:1; |
148 | unsigned int max_indirect_segments; | 149 | unsigned int max_indirect_segments; |
149 | int is_ready; | 150 | int is_ready; |
151 | struct blk_mq_tag_set tag_set; | ||
150 | }; | 152 | }; |
151 | 153 | ||
152 | static unsigned int nr_minors; | 154 | static unsigned int nr_minors; |
@@ -616,54 +618,41 @@ static inline bool blkif_request_flush_invalid(struct request *req, | |||
616 | !(info->feature_flush & REQ_FUA))); | 618 | !(info->feature_flush & REQ_FUA))); |
617 | } | 619 | } |
618 | 620 | ||
619 | /* | 621 | static int blkif_queue_rq(struct blk_mq_hw_ctx *hctx, |
620 | * do_blkif_request | 622 | const struct blk_mq_queue_data *qd) |
621 | * read a block; request is in a request queue | ||
622 | */ | ||
623 | static void do_blkif_request(struct request_queue *rq) | ||
624 | { | 623 | { |
625 | struct blkfront_info *info = NULL; | 624 | struct blkfront_info *info = qd->rq->rq_disk->private_data; |
626 | struct request *req; | ||
627 | int queued; | ||
628 | |||
629 | pr_debug("Entered do_blkif_request\n"); | ||
630 | |||
631 | queued = 0; | ||
632 | 625 | ||
633 | while ((req = blk_peek_request(rq)) != NULL) { | 626 | blk_mq_start_request(qd->rq); |
634 | info = req->rq_disk->private_data; | 627 | spin_lock_irq(&info->io_lock); |
635 | 628 | if (RING_FULL(&info->ring)) | |
636 | if (RING_FULL(&info->ring)) | 629 | goto out_busy; |
637 | goto wait; | ||
638 | 630 | ||
639 | blk_start_request(req); | 631 | if (blkif_request_flush_invalid(qd->rq, info)) |
632 | goto out_err; | ||
640 | 633 | ||
641 | if (blkif_request_flush_invalid(req, info)) { | 634 | if (blkif_queue_request(qd->rq)) |
642 | __blk_end_request_all(req, -EOPNOTSUPP); | 635 | goto out_busy; |
643 | continue; | ||
644 | } | ||
645 | 636 | ||
646 | pr_debug("do_blk_req %p: cmd %p, sec %lx, " | 637 | flush_requests(info); |
647 | "(%u/%u) [%s]\n", | 638 | spin_unlock_irq(&info->io_lock); |
648 | req, req->cmd, (unsigned long)blk_rq_pos(req), | 639 | return BLK_MQ_RQ_QUEUE_OK; |
649 | blk_rq_cur_sectors(req), blk_rq_sectors(req), | ||
650 | rq_data_dir(req) ? "write" : "read"); | ||
651 | |||
652 | if (blkif_queue_request(req)) { | ||
653 | blk_requeue_request(rq, req); | ||
654 | wait: | ||
655 | /* Avoid pointless unplugs. */ | ||
656 | blk_stop_queue(rq); | ||
657 | break; | ||
658 | } | ||
659 | 640 | ||
660 | queued++; | 641 | out_err: |
661 | } | 642 | spin_unlock_irq(&info->io_lock); |
643 | return BLK_MQ_RQ_QUEUE_ERROR; | ||
662 | 644 | ||
663 | if (queued != 0) | 645 | out_busy: |
664 | flush_requests(info); | 646 | spin_unlock_irq(&info->io_lock); |
647 | blk_mq_stop_hw_queue(hctx); | ||
648 | return BLK_MQ_RQ_QUEUE_BUSY; | ||
665 | } | 649 | } |
666 | 650 | ||
651 | static struct blk_mq_ops blkfront_mq_ops = { | ||
652 | .queue_rq = blkif_queue_rq, | ||
653 | .map_queue = blk_mq_map_queue, | ||
654 | }; | ||
655 | |||
667 | static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, | 656 | static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, |
668 | unsigned int physical_sector_size, | 657 | unsigned int physical_sector_size, |
669 | unsigned int segments) | 658 | unsigned int segments) |
@@ -671,9 +660,22 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, | |||
671 | struct request_queue *rq; | 660 | struct request_queue *rq; |
672 | struct blkfront_info *info = gd->private_data; | 661 | struct blkfront_info *info = gd->private_data; |
673 | 662 | ||
674 | rq = blk_init_queue(do_blkif_request, &info->io_lock); | 663 | memset(&info->tag_set, 0, sizeof(info->tag_set)); |
675 | if (rq == NULL) | 664 | info->tag_set.ops = &blkfront_mq_ops; |
665 | info->tag_set.nr_hw_queues = 1; | ||
666 | info->tag_set.queue_depth = BLK_RING_SIZE(info); | ||
667 | info->tag_set.numa_node = NUMA_NO_NODE; | ||
668 | info->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; | ||
669 | info->tag_set.cmd_size = 0; | ||
670 | info->tag_set.driver_data = info; | ||
671 | |||
672 | if (blk_mq_alloc_tag_set(&info->tag_set)) | ||
676 | return -1; | 673 | return -1; |
674 | rq = blk_mq_init_queue(&info->tag_set); | ||
675 | if (IS_ERR(rq)) { | ||
676 | blk_mq_free_tag_set(&info->tag_set); | ||
677 | return -1; | ||
678 | } | ||
677 | 679 | ||
678 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); | 680 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); |
679 | 681 | ||
@@ -901,19 +903,15 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
901 | static void xlvbd_release_gendisk(struct blkfront_info *info) | 903 | static void xlvbd_release_gendisk(struct blkfront_info *info) |
902 | { | 904 | { |
903 | unsigned int minor, nr_minors; | 905 | unsigned int minor, nr_minors; |
904 | unsigned long flags; | ||
905 | 906 | ||
906 | if (info->rq == NULL) | 907 | if (info->rq == NULL) |
907 | return; | 908 | return; |
908 | 909 | ||
909 | spin_lock_irqsave(&info->io_lock, flags); | ||
910 | |||
911 | /* No more blkif_request(). */ | 910 | /* No more blkif_request(). */ |
912 | blk_stop_queue(info->rq); | 911 | blk_mq_stop_hw_queues(info->rq); |
913 | 912 | ||
914 | /* No more gnttab callback work. */ | 913 | /* No more gnttab callback work. */ |
915 | gnttab_cancel_free_callback(&info->callback); | 914 | gnttab_cancel_free_callback(&info->callback); |
916 | spin_unlock_irqrestore(&info->io_lock, flags); | ||
917 | 915 | ||
918 | /* Flush gnttab callback work. Must be done with no locks held. */ | 916 | /* Flush gnttab callback work. Must be done with no locks held. */ |
919 | flush_work(&info->work); | 917 | flush_work(&info->work); |
@@ -925,20 +923,18 @@ static void xlvbd_release_gendisk(struct blkfront_info *info) | |||
925 | xlbd_release_minors(minor, nr_minors); | 923 | xlbd_release_minors(minor, nr_minors); |
926 | 924 | ||
927 | blk_cleanup_queue(info->rq); | 925 | blk_cleanup_queue(info->rq); |
926 | blk_mq_free_tag_set(&info->tag_set); | ||
928 | info->rq = NULL; | 927 | info->rq = NULL; |
929 | 928 | ||
930 | put_disk(info->gd); | 929 | put_disk(info->gd); |
931 | info->gd = NULL; | 930 | info->gd = NULL; |
932 | } | 931 | } |
933 | 932 | ||
933 | /* Must be called with io_lock holded */ | ||
934 | static void kick_pending_request_queues(struct blkfront_info *info) | 934 | static void kick_pending_request_queues(struct blkfront_info *info) |
935 | { | 935 | { |
936 | if (!RING_FULL(&info->ring)) { | 936 | if (!RING_FULL(&info->ring)) |
937 | /* Re-enable calldowns. */ | 937 | blk_mq_start_stopped_hw_queues(info->rq, true); |
938 | blk_start_queue(info->rq); | ||
939 | /* Kick things off immediately. */ | ||
940 | do_blkif_request(info->rq); | ||
941 | } | ||
942 | } | 938 | } |
943 | 939 | ||
944 | static void blkif_restart_queue(struct work_struct *work) | 940 | static void blkif_restart_queue(struct work_struct *work) |
@@ -963,7 +959,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
963 | BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; | 959 | BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED; |
964 | /* No more blkif_request(). */ | 960 | /* No more blkif_request(). */ |
965 | if (info->rq) | 961 | if (info->rq) |
966 | blk_stop_queue(info->rq); | 962 | blk_mq_stop_hw_queues(info->rq); |
967 | 963 | ||
968 | /* Remove all persistent grants */ | 964 | /* Remove all persistent grants */ |
969 | if (!list_empty(&info->grants)) { | 965 | if (!list_empty(&info->grants)) { |
@@ -1146,7 +1142,6 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
1146 | RING_IDX i, rp; | 1142 | RING_IDX i, rp; |
1147 | unsigned long flags; | 1143 | unsigned long flags; |
1148 | struct blkfront_info *info = (struct blkfront_info *)dev_id; | 1144 | struct blkfront_info *info = (struct blkfront_info *)dev_id; |
1149 | int error; | ||
1150 | 1145 | ||
1151 | spin_lock_irqsave(&info->io_lock, flags); | 1146 | spin_lock_irqsave(&info->io_lock, flags); |
1152 | 1147 | ||
@@ -1187,37 +1182,37 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
1187 | continue; | 1182 | continue; |
1188 | } | 1183 | } |
1189 | 1184 | ||
1190 | error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; | 1185 | req->errors = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; |
1191 | switch (bret->operation) { | 1186 | switch (bret->operation) { |
1192 | case BLKIF_OP_DISCARD: | 1187 | case BLKIF_OP_DISCARD: |
1193 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 1188 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
1194 | struct request_queue *rq = info->rq; | 1189 | struct request_queue *rq = info->rq; |
1195 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", | 1190 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
1196 | info->gd->disk_name, op_name(bret->operation)); | 1191 | info->gd->disk_name, op_name(bret->operation)); |
1197 | error = -EOPNOTSUPP; | 1192 | req->errors = -EOPNOTSUPP; |
1198 | info->feature_discard = 0; | 1193 | info->feature_discard = 0; |
1199 | info->feature_secdiscard = 0; | 1194 | info->feature_secdiscard = 0; |
1200 | queue_flag_clear(QUEUE_FLAG_DISCARD, rq); | 1195 | queue_flag_clear(QUEUE_FLAG_DISCARD, rq); |
1201 | queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq); | 1196 | queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq); |
1202 | } | 1197 | } |
1203 | __blk_end_request_all(req, error); | 1198 | blk_mq_complete_request(req); |
1204 | break; | 1199 | break; |
1205 | case BLKIF_OP_FLUSH_DISKCACHE: | 1200 | case BLKIF_OP_FLUSH_DISKCACHE: |
1206 | case BLKIF_OP_WRITE_BARRIER: | 1201 | case BLKIF_OP_WRITE_BARRIER: |
1207 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 1202 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
1208 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", | 1203 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
1209 | info->gd->disk_name, op_name(bret->operation)); | 1204 | info->gd->disk_name, op_name(bret->operation)); |
1210 | error = -EOPNOTSUPP; | 1205 | req->errors = -EOPNOTSUPP; |
1211 | } | 1206 | } |
1212 | if (unlikely(bret->status == BLKIF_RSP_ERROR && | 1207 | if (unlikely(bret->status == BLKIF_RSP_ERROR && |
1213 | info->shadow[id].req.u.rw.nr_segments == 0)) { | 1208 | info->shadow[id].req.u.rw.nr_segments == 0)) { |
1214 | printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", | 1209 | printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", |
1215 | info->gd->disk_name, op_name(bret->operation)); | 1210 | info->gd->disk_name, op_name(bret->operation)); |
1216 | error = -EOPNOTSUPP; | 1211 | req->errors = -EOPNOTSUPP; |
1217 | } | 1212 | } |
1218 | if (unlikely(error)) { | 1213 | if (unlikely(req->errors)) { |
1219 | if (error == -EOPNOTSUPP) | 1214 | if (req->errors == -EOPNOTSUPP) |
1220 | error = 0; | 1215 | req->errors = 0; |
1221 | info->feature_flush = 0; | 1216 | info->feature_flush = 0; |
1222 | xlvbd_flush(info); | 1217 | xlvbd_flush(info); |
1223 | } | 1218 | } |
@@ -1228,7 +1223,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
1228 | dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " | 1223 | dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " |
1229 | "request: %x\n", bret->status); | 1224 | "request: %x\n", bret->status); |
1230 | 1225 | ||
1231 | __blk_end_request_all(req, error); | 1226 | blk_mq_complete_request(req); |
1232 | break; | 1227 | break; |
1233 | default: | 1228 | default: |
1234 | BUG(); | 1229 | BUG(); |
@@ -1555,28 +1550,6 @@ static int blkif_recover(struct blkfront_info *info) | |||
1555 | 1550 | ||
1556 | kfree(copy); | 1551 | kfree(copy); |
1557 | 1552 | ||
1558 | /* | ||
1559 | * Empty the queue, this is important because we might have | ||
1560 | * requests in the queue with more segments than what we | ||
1561 | * can handle now. | ||
1562 | */ | ||
1563 | spin_lock_irq(&info->io_lock); | ||
1564 | while ((req = blk_fetch_request(info->rq)) != NULL) { | ||
1565 | if (req->cmd_flags & | ||
1566 | (REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) { | ||
1567 | list_add(&req->queuelist, &requests); | ||
1568 | continue; | ||
1569 | } | ||
1570 | merge_bio.head = req->bio; | ||
1571 | merge_bio.tail = req->biotail; | ||
1572 | bio_list_merge(&bio_list, &merge_bio); | ||
1573 | req->bio = NULL; | ||
1574 | if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) | ||
1575 | pr_alert("diskcache flush request found!\n"); | ||
1576 | __blk_end_request_all(req, 0); | ||
1577 | } | ||
1578 | spin_unlock_irq(&info->io_lock); | ||
1579 | |||
1580 | xenbus_switch_state(info->xbdev, XenbusStateConnected); | 1553 | xenbus_switch_state(info->xbdev, XenbusStateConnected); |
1581 | 1554 | ||
1582 | spin_lock_irq(&info->io_lock); | 1555 | spin_lock_irq(&info->io_lock); |
@@ -1591,9 +1564,10 @@ static int blkif_recover(struct blkfront_info *info) | |||
1591 | /* Requeue pending requests (flush or discard) */ | 1564 | /* Requeue pending requests (flush or discard) */ |
1592 | list_del_init(&req->queuelist); | 1565 | list_del_init(&req->queuelist); |
1593 | BUG_ON(req->nr_phys_segments > segs); | 1566 | BUG_ON(req->nr_phys_segments > segs); |
1594 | blk_requeue_request(info->rq, req); | 1567 | blk_mq_requeue_request(req); |
1595 | } | 1568 | } |
1596 | spin_unlock_irq(&info->io_lock); | 1569 | spin_unlock_irq(&info->io_lock); |
1570 | blk_mq_kick_requeue_list(info->rq); | ||
1597 | 1571 | ||
1598 | while ((bio = bio_list_pop(&bio_list)) != NULL) { | 1572 | while ((bio = bio_list_pop(&bio_list)) != NULL) { |
1599 | /* Traverse the list of pending bios and re-queue them */ | 1573 | /* Traverse the list of pending bios and re-queue them */ |