diff options
| -rw-r--r-- | drivers/block/xen-blkback/common.h | 2 | ||||
| -rw-r--r-- | drivers/block/xen-blkfront.c | 58 |
2 files changed, 48 insertions, 12 deletions
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 773cf27dc23f..9ad3b5ec1dc1 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
| @@ -257,6 +257,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, | |||
| 257 | break; | 257 | break; |
| 258 | case BLKIF_OP_DISCARD: | 258 | case BLKIF_OP_DISCARD: |
| 259 | dst->u.discard.flag = src->u.discard.flag; | 259 | dst->u.discard.flag = src->u.discard.flag; |
| 260 | dst->u.discard.id = src->u.discard.id; | ||
| 260 | dst->u.discard.sector_number = src->u.discard.sector_number; | 261 | dst->u.discard.sector_number = src->u.discard.sector_number; |
| 261 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 262 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
| 262 | break; | 263 | break; |
| @@ -287,6 +288,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, | |||
| 287 | break; | 288 | break; |
| 288 | case BLKIF_OP_DISCARD: | 289 | case BLKIF_OP_DISCARD: |
| 289 | dst->u.discard.flag = src->u.discard.flag; | 290 | dst->u.discard.flag = src->u.discard.flag; |
| 291 | dst->u.discard.id = src->u.discard.id; | ||
| 290 | dst->u.discard.sector_number = src->u.discard.sector_number; | 292 | dst->u.discard.sector_number = src->u.discard.sector_number; |
| 291 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 293 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
| 292 | break; | 294 | break; |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 60eed4bdd2e4..e4fb3374dcd2 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
| @@ -141,14 +141,36 @@ static int get_id_from_freelist(struct blkfront_info *info) | |||
| 141 | return free; | 141 | return free; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static void add_id_to_freelist(struct blkfront_info *info, | 144 | static int add_id_to_freelist(struct blkfront_info *info, |
| 145 | unsigned long id) | 145 | unsigned long id) |
| 146 | { | 146 | { |
| 147 | if (info->shadow[id].req.u.rw.id != id) | ||
| 148 | return -EINVAL; | ||
| 149 | if (info->shadow[id].request == NULL) | ||
| 150 | return -EINVAL; | ||
| 147 | info->shadow[id].req.u.rw.id = info->shadow_free; | 151 | info->shadow[id].req.u.rw.id = info->shadow_free; |
| 148 | info->shadow[id].request = NULL; | 152 | info->shadow[id].request = NULL; |
| 149 | info->shadow_free = id; | 153 | info->shadow_free = id; |
| 154 | return 0; | ||
| 150 | } | 155 | } |
| 151 | 156 | ||
| 157 | static const char *op_name(int op) | ||
| 158 | { | ||
| 159 | static const char *const names[] = { | ||
| 160 | [BLKIF_OP_READ] = "read", | ||
| 161 | [BLKIF_OP_WRITE] = "write", | ||
| 162 | [BLKIF_OP_WRITE_BARRIER] = "barrier", | ||
| 163 | [BLKIF_OP_FLUSH_DISKCACHE] = "flush", | ||
| 164 | [BLKIF_OP_DISCARD] = "discard" }; | ||
| 165 | |||
| 166 | if (op < 0 || op >= ARRAY_SIZE(names)) | ||
| 167 | return "unknown"; | ||
| 168 | |||
| 169 | if (!names[op]) | ||
| 170 | return "reserved"; | ||
| 171 | |||
| 172 | return names[op]; | ||
| 173 | } | ||
| 152 | static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) | 174 | static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) |
| 153 | { | 175 | { |
| 154 | unsigned int end = minor + nr; | 176 | unsigned int end = minor + nr; |
| @@ -746,20 +768,36 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
| 746 | 768 | ||
| 747 | bret = RING_GET_RESPONSE(&info->ring, i); | 769 | bret = RING_GET_RESPONSE(&info->ring, i); |
| 748 | id = bret->id; | 770 | id = bret->id; |
| 771 | /* | ||
| 772 | * The backend has messed up and given us an id that we would | ||
| 773 | * never have given to it (we stamp it up to BLK_RING_SIZE - | ||
| 774 | * look in get_id_from_freelist. | ||
| 775 | */ | ||
| 776 | if (id >= BLK_RING_SIZE) { | ||
| 777 | WARN(1, "%s: response to %s has incorrect id (%ld)\n", | ||
| 778 | info->gd->disk_name, op_name(bret->operation), id); | ||
| 779 | /* We can't safely get the 'struct request' as | ||
| 780 | * the id is busted. */ | ||
| 781 | continue; | ||
| 782 | } | ||
| 749 | req = info->shadow[id].request; | 783 | req = info->shadow[id].request; |
| 750 | 784 | ||
| 751 | if (bret->operation != BLKIF_OP_DISCARD) | 785 | if (bret->operation != BLKIF_OP_DISCARD) |
| 752 | blkif_completion(&info->shadow[id]); | 786 | blkif_completion(&info->shadow[id]); |
| 753 | 787 | ||
| 754 | add_id_to_freelist(info, id); | 788 | if (add_id_to_freelist(info, id)) { |
| 789 | WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n", | ||
| 790 | info->gd->disk_name, op_name(bret->operation), id); | ||
| 791 | continue; | ||
| 792 | } | ||
| 755 | 793 | ||
| 756 | error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; | 794 | error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; |
| 757 | switch (bret->operation) { | 795 | switch (bret->operation) { |
| 758 | case BLKIF_OP_DISCARD: | 796 | case BLKIF_OP_DISCARD: |
| 759 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 797 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
| 760 | struct request_queue *rq = info->rq; | 798 | struct request_queue *rq = info->rq; |
| 761 | printk(KERN_WARNING "blkfront: %s: discard op failed\n", | 799 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
| 762 | info->gd->disk_name); | 800 | info->gd->disk_name, op_name(bret->operation)); |
| 763 | error = -EOPNOTSUPP; | 801 | error = -EOPNOTSUPP; |
| 764 | info->feature_discard = 0; | 802 | info->feature_discard = 0; |
| 765 | info->feature_secdiscard = 0; | 803 | info->feature_secdiscard = 0; |
| @@ -771,18 +809,14 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
| 771 | case BLKIF_OP_FLUSH_DISKCACHE: | 809 | case BLKIF_OP_FLUSH_DISKCACHE: |
| 772 | case BLKIF_OP_WRITE_BARRIER: | 810 | case BLKIF_OP_WRITE_BARRIER: |
| 773 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 811 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
| 774 | printk(KERN_WARNING "blkfront: %s: write %s op failed\n", | 812 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
| 775 | info->flush_op == BLKIF_OP_WRITE_BARRIER ? | 813 | info->gd->disk_name, op_name(bret->operation)); |
| 776 | "barrier" : "flush disk cache", | ||
| 777 | info->gd->disk_name); | ||
| 778 | error = -EOPNOTSUPP; | 814 | error = -EOPNOTSUPP; |
| 779 | } | 815 | } |
| 780 | if (unlikely(bret->status == BLKIF_RSP_ERROR && | 816 | if (unlikely(bret->status == BLKIF_RSP_ERROR && |
| 781 | info->shadow[id].req.u.rw.nr_segments == 0)) { | 817 | info->shadow[id].req.u.rw.nr_segments == 0)) { |
| 782 | printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n", | 818 | printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", |
| 783 | info->flush_op == BLKIF_OP_WRITE_BARRIER ? | 819 | info->gd->disk_name, op_name(bret->operation)); |
| 784 | "barrier" : "flush disk cache", | ||
| 785 | info->gd->disk_name); | ||
| 786 | error = -EOPNOTSUPP; | 820 | error = -EOPNOTSUPP; |
| 787 | } | 821 | } |
| 788 | if (unlikely(error)) { | 822 | if (unlikely(error)) { |
