Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / block / xen-blkback / blkback.c
index d06eb6a..5cf2993 100644 (file)
@@ -71,7 +71,7 @@ module_param(log_stats, int, 0644);
  * response queued for it, with the saved 'id' passed back.
  */
 struct pending_req {
-       struct blkif_st         *blkif;
+       struct xen_blkif        *blkif;
        u64                     id;
        int                     nr_pages;
        atomic_t                pendcnt;
@@ -121,11 +121,11 @@ static inline unsigned long vaddr(struct pending_req *req, int seg)
        (blkbk->pending_grant_handles[vaddr_pagenr(_req, _seg)])
 
 
-static int do_block_io_op(struct blkif_st *blkif);
-static int dispatch_rw_block_io(struct blkif_st *blkif,
+static int do_block_io_op(struct xen_blkif *blkif);
+static int dispatch_rw_block_io(struct xen_blkif *blkif,
                                struct blkif_request *req,
                                struct pending_req *pending_req);
-static void make_response(struct blkif_st *blkif, u64 id,
+static void make_response(struct xen_blkif *blkif, u64 id,
                          unsigned short op, int st);
 
 /*
@@ -166,17 +166,23 @@ static void free_req(struct pending_req *req)
 /*
  * Routines for managing virtual block devices (vbds).
  */
-static int vbd_translate(struct phys_req *req, struct blkif_st *blkif,
-                        int operation)
+static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif,
+                            int operation)
 {
-       struct vbd *vbd = &blkif->vbd;
+       struct xen_vbd *vbd = &blkif->vbd;
        int rc = -EACCES;
 
        if ((operation != READ) && vbd->readonly)
                goto out;
 
-       if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
-               goto out;
+       if (likely(req->nr_sects)) {
+               blkif_sector_t end = req->sector_number + req->nr_sects;
+
+               if (unlikely(end < req->sector_number))
+                       goto out;
+               if (unlikely(end > vbd_sz(vbd)))
+                       goto out;
+       }
 
        req->dev  = vbd->pdevice;
        req->bdev = vbd->bdev;
@@ -186,9 +192,9 @@ static int vbd_translate(struct phys_req *req, struct blkif_st *blkif,
        return rc;
 }
 
-static void vbd_resize(struct blkif_st *blkif)
+static void xen_vbd_resize(struct xen_blkif *blkif)
 {
-       struct vbd *vbd = &blkif->vbd;
+       struct xen_vbd *vbd = &blkif->vbd;
        struct xenbus_transaction xbt;
        int err;
        struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be);
@@ -226,6 +232,7 @@ again:
                goto again;
        if (err)
                pr_warn(DRV_PFX "Error ending transaction");
+       return;
 abort:
        xenbus_transaction_end(xbt, 1);
 }
@@ -233,7 +240,7 @@ abort:
 /*
  * Notification from the guest OS.
  */
-static void blkif_notify_work(struct blkif_st *blkif)
+static void blkif_notify_work(struct xen_blkif *blkif)
 {
        blkif->waiting_reqs = 1;
        wake_up(&blkif->wq);
@@ -249,9 +256,9 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id)
  * SCHEDULER FUNCTIONS
  */
 
-static void print_stats(struct blkif_st *blkif)
+static void print_stats(struct xen_blkif *blkif)
 {
-       pr_debug("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d\n",
+       pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d\n",
                 current->comm, blkif->st_oo_req,
                 blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req);
        blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
@@ -262,8 +269,8 @@ static void print_stats(struct blkif_st *blkif)
 
 int xen_blkif_schedule(void *arg)
 {
-       struct blkif_st *blkif = arg;
-       struct vbd *vbd = &blkif->vbd;
+       struct xen_blkif *blkif = arg;
+       struct xen_vbd *vbd = &blkif->vbd;
 
        xen_blkif_get(blkif);
 
@@ -271,7 +278,7 @@ int xen_blkif_schedule(void *arg)
                if (try_to_freeze())
                        continue;
                if (unlikely(vbd->size != vbd_sz(vbd)))
-                       vbd_resize(blkif);
+                       xen_vbd_resize(blkif);
 
                wait_event_interruptible(
                        blkif->wq,
@@ -451,7 +458,7 @@ static void end_block_io_op(struct bio *bio, int error)
  * (which has the sectors we want, number of them, grant references, etc),
  * and transmute  it to the block API to hand it over to the proper block disk.
  */
-static int do_block_io_op(struct blkif_st *blkif)
+static int do_block_io_op(struct xen_blkif *blkif)
 {
        union blkif_back_rings *blk_rings = &blkif->blk_rings;
        struct blkif_request req;
@@ -512,9 +519,9 @@ static int do_block_io_op(struct blkif_st *blkif)
  * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
  * and call the 'submit_bio' to pass it to the underlying storage.
  */
-static int dispatch_rw_block_io(struct blkif_st *blkif,
-                                struct blkif_request *req,
-                                struct pending_req *pending_req)
+static int dispatch_rw_block_io(struct xen_blkif *blkif,
+                               struct blkif_request *req,
+                               struct pending_req *pending_req)
 {
        struct phys_req preq;
        struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
@@ -537,11 +544,6 @@ static int dispatch_rw_block_io(struct blkif_st *blkif,
        case BLKIF_OP_FLUSH_DISKCACHE:
                blkif->st_f_req++;
                operation = WRITE_FLUSH;
-               /*
-                * The frontend likes to set this to -1, which vbd_translate
-                * is alergic too.
-                */
-               req->u.rw.sector_number = 0;
                break;
        case BLKIF_OP_WRITE_BARRIER:
        default:
@@ -580,7 +582,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif,
 
        }
 
-       if (vbd_translate(&preq, blkif, operation) != 0) {
+       if (xen_vbd_translate(&preq, blkif, operation) != 0) {
                pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n",
                         operation == READ ? "read" : "write",
                         preq.sector_number,
@@ -589,7 +591,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif,
        }
 
        /*
-        * This check _MUST_ be done after vbd_translate as the preq.bdev
+        * This check _MUST_ be done after xen_vbd_translate as the preq.bdev
         * is set there.
         */
        for (i = 0; i < nseg; i++) {
@@ -692,7 +694,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif,
 /*
  * Put a response on the ring on how the operation fared.
  */
-static void make_response(struct blkif_st *blkif, u64 id,
+static void make_response(struct xen_blkif *blkif, u64 id,
                          unsigned short op, int st)
 {
        struct blkif_response  resp;
@@ -807,11 +809,13 @@ static int __init xen_blkif_init(void)
  failed_init:
        kfree(blkbk->pending_reqs);
        kfree(blkbk->pending_grant_handles);
-       for (i = 0; i < mmap_pages; i++) {
-               if (blkbk->pending_pages[i])
-                       __free_page(blkbk->pending_pages[i]);
+       if (blkbk->pending_pages) {
+               for (i = 0; i < mmap_pages; i++) {
+                       if (blkbk->pending_pages[i])
+                               __free_page(blkbk->pending_pages[i]);
+               }
+               kfree(blkbk->pending_pages);
        }
-       kfree(blkbk->pending_pages);
        kfree(blkbk);
        blkbk = NULL;
        return rc;