]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/block/xen-blkback/blkback.c
Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux...
[karo-tx-linux.git] / drivers / block / xen-blkback / blkback.c
index de1f319f7bd7e0118a960b5bd23fd286a6ba343e..dd5b2fed97e9ae2b7665f13ec3c42db6ee6fb462 100644 (file)
@@ -164,7 +164,7 @@ static void make_response(struct xen_blkif *blkif, u64 id,
 
 #define foreach_grant_safe(pos, n, rbtree, node) \
        for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
-            (n) = rb_next(&(pos)->node); \
+            (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL; \
             &(pos)->node != NULL; \
             (pos) = container_of(n, typeof(*(pos)), node), \
             (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
@@ -381,8 +381,8 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id)
 
 static void print_stats(struct xen_blkif *blkif)
 {
-       pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d"
-                "  |  ds %4d\n",
+       pr_info("xen-blkback (%s): oo %3llu  |  rd %4llu  |  wr %4llu  |  f %4llu"
+                "  |  ds %4llu\n",
                 current->comm, blkif->st_oo_req,
                 blkif->st_rd_req, blkif->st_wr_req,
                 blkif->st_f_req, blkif->st_ds_req);
@@ -442,7 +442,7 @@ int xen_blkif_schedule(void *arg)
 }
 
 struct seg_buf {
-       unsigned long buf;
+       unsigned int offset;
        unsigned int nsec;
 };
 /*
@@ -621,30 +621,21 @@ static int xen_blkbk_map(struct blkif_request *req,
                                 * If this is a new persistent grant
                                 * save the handler
                                 */
-                               persistent_gnts[i]->handle = map[j].handle;
-                               persistent_gnts[i]->dev_bus_addr =
-                                       map[j++].dev_bus_addr;
+                               persistent_gnts[i]->handle = map[j++].handle;
                        }
                        pending_handle(pending_req, i) =
                                persistent_gnts[i]->handle;
 
                        if (ret)
                                continue;
-
-                       seg[i].buf = persistent_gnts[i]->dev_bus_addr |
-                               (req->u.rw.seg[i].first_sect << 9);
                } else {
-                       pending_handle(pending_req, i) = map[j].handle;
+                       pending_handle(pending_req, i) = map[j++].handle;
                        bitmap_set(pending_req->unmap_seg, i, 1);
 
-                       if (ret) {
-                               j++;
+                       if (ret)
                                continue;
-                       }
-
-                       seg[i].buf = map[j++].dev_bus_addr |
-                               (req->u.rw.seg[i].first_sect << 9);
                }
+               seg[i].offset = (req->u.rw.seg[i].first_sect << 9);
        }
        return ret;
 }
@@ -679,6 +670,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
        return err;
 }
 
+static int dispatch_other_io(struct xen_blkif *blkif,
+                            struct blkif_request *req,
+                            struct pending_req *pending_req)
+{
+       free_req(pending_req);
+       make_response(blkif, req->u.other.id, req->operation,
+                     BLKIF_RSP_EOPNOTSUPP);
+       return -EIO;
+}
+
 static void xen_blk_drain_io(struct xen_blkif *blkif)
 {
        atomic_set(&blkif->drain, 1);
@@ -800,17 +801,30 @@ __do_block_io_op(struct xen_blkif *blkif)
 
                /* Apply all sanity checks to /private copy/ of request. */
                barrier();
-               if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+
+               switch (req.operation) {
+               case BLKIF_OP_READ:
+               case BLKIF_OP_WRITE:
+               case BLKIF_OP_WRITE_BARRIER:
+               case BLKIF_OP_FLUSH_DISKCACHE:
+                       if (dispatch_rw_block_io(blkif, &req, pending_req))
+                               goto done;
+                       break;
+               case BLKIF_OP_DISCARD:
                        free_req(pending_req);
                        if (dispatch_discard_io(blkif, &req))
-                               break;
-               } else if (dispatch_rw_block_io(blkif, &req, pending_req))
+                               goto done;
                        break;
+               default:
+                       if (dispatch_other_io(blkif, &req, pending_req))
+                               goto done;
+                       break;
+               }
 
                /* Yield point for this unbounded loop. */
                cond_resched();
        }
-
+done:
        return more_to_do;
 }
 
@@ -904,7 +918,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n",
                         operation == READ ? "read" : "write",
                         preq.sector_number,
-                        preq.sector_number + preq.nr_sects, preq.dev);
+                        preq.sector_number + preq.nr_sects,
+                        blkif->vbd.pdevice);
                goto fail_response;
        }
 
@@ -947,7 +962,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                       (bio_add_page(bio,
                                     pages[i],
                                     seg[i].nsec << 9,
-                                    seg[i].buf & ~PAGE_MASK) == 0)) {
+                                    seg[i].offset) == 0)) {
 
                        bio = bio_alloc(GFP_KERNEL, nseg-i);
                        if (unlikely(bio == NULL))
@@ -977,13 +992,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                bio->bi_end_io  = end_block_io_op;
        }
 
-       /*
-        * We set it one so that the last submit_bio does not have to call
-        * atomic_inc.
-        */
        atomic_set(&pending_req->pendcnt, nbio);
-
-       /* Get a reference count for the disk queue and start sending I/O */
        blk_start_plug(&plug);
 
        for (i = 0; i < nbio; i++)
@@ -1011,6 +1020,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
  fail_put_bio:
        for (i = 0; i < nbio; i++)
                bio_put(biolist[i]);
+       atomic_set(&pending_req->pendcnt, 1);
        __end_block_io_op(pending_req, -EINVAL);
        msleep(1); /* back off a bit */
        return -EIO;