aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2012-06-13 15:19:06 -0400
committerJens Axboe <axboe@kernel.dk>2012-06-13 15:19:06 -0400
commit987751719bd38a72dfd29f398dea1a7f3cd5b224 (patch)
treea6a921813997caf7360771620667cdc2a83c99c1
parent32587371ad3db2f9d335de10dbd8cffd4fff5669 (diff)
parent6878c32e5cc0e40980abe51d1f02fb453e27493e (diff)
Merge branch 'stable/for-jens-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen into for-linus
-rw-r--r--drivers/block/xen-blkback/common.h2
-rw-r--r--drivers/block/xen-blkfront.c58
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
144static void add_id_to_freelist(struct blkfront_info *info, 144static 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
157static 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}
152static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) 174static 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)) {