]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Merge branches 'stable/xen-block.rebase' and 'stable/vmalloc-3.2.rebased' into uek2...
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 13 Dec 2011 16:15:27 +0000 (11:15 -0500)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 13 Dec 2011 16:15:27 +0000 (11:15 -0500)
* stable/xen-block.rebase:
  xen-blkback: Don't disconnect backend until state switched to XenbusStateClosed.
  block: xen-blkback: use API provided by xenbus module to map rings
  xen-blkback: convert hole punching to discard request on loop devices
  xen/blkback: Move processing of BLKIF_OP_DISCARD from dispatch_rw_block_io
  xen/blk[front|back]: Enhance discard support with secure erasing support.
  xen/blk[front|back]: Squash blkif_request_rw and blkif_request_discard together

* stable/vmalloc-3.2.rebased:
  xen: map foreign pages for shared rings by updating the PTEs directly
  net: xen-netback: use API provided by xenbus module to map rings
  block: xen-blkback: use API provided by xenbus module to map rings
  xen: use generic functions instead of xen_{alloc, free}_vm_area()

1  2  3 
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/net/xen-netback/netback.c
include/xen/grant_table.h
mm/vmalloc.c

index 8d6e35a8e28e8eaf639b240658a156ff254baa81,b75d4a9aa08b7dfd8ab2242da026ebac33b7ed58,5cf2993a8338c9e325fb6126d5a6ec3ca371f6e3..4dde715fc445dca5b800acbd64c0027e543d9703
@@@@ -416,59 -413,56 -410,6 +413,56 @@@@ static int xen_blkbk_map(struct blkif_r
        return ret;
   }
   
-  static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+ +static int dispatch_discard_io(struct xen_blkif *blkif,
+ +                             struct blkif_request *req)
  +{
  +     int err = 0;
  +     int status = BLKIF_RSP_OKAY;
  +     struct block_device *bdev = blkif->vbd.bdev;
  +
-       if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
-               /* just forward the discard request */
+ +     blkif->st_ds_req++;
+ +
+ +     xen_blkif_get(blkif);
+ +     if (blkif->blk_backend_type == BLKIF_BACKEND_PHY ||
+ +         blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+ +             unsigned long secure = (blkif->vbd.discard_secure &&
+ +                     (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
+ +                     BLKDEV_DISCARD_SECURE : 0;
  +             err = blkdev_issue_discard(bdev,
  +                             req->u.discard.sector_number,
  +                             req->u.discard.nr_sectors,
-                               GFP_KERNEL, 0);
-       else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
-               /* punch a hole in the backing file */
-               struct loop_device *lo = bdev->bd_disk->private_data;
-               struct file *file = lo->lo_backing_file;
-  
-               if (file->f_op->fallocate)
-                       err = file->f_op->fallocate(file,
-                               FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
-                               req->u.discard.sector_number << 9,
-                               req->u.discard.nr_sectors << 9);
-               else
-                       err = -EOPNOTSUPP;
+ +                             GFP_KERNEL, secure);
  +     } else
  +             err = -EOPNOTSUPP;
  +
  +     if (err == -EOPNOTSUPP) {
  +             pr_debug(DRV_PFX "discard op failed, not supported\n");
  +             status = BLKIF_RSP_EOPNOTSUPP;
  +     } else if (err)
  +             status = BLKIF_RSP_ERROR;
  +
-       make_response(blkif, req->id, req->operation, status);
+ +     make_response(blkif, req->u.discard.id, req->operation, status);
+ +     xen_blkif_put(blkif);
+ +     return err;
  +}
  +
  +static void xen_blk_drain_io(struct xen_blkif *blkif)
  +{
  +     atomic_set(&blkif->drain, 1);
  +     do {
  +             /* The initial value is one, and one refcnt taken at the
  +              * start of the xen_blkif_schedule thread. */
  +             if (atomic_read(&blkif->refcnt) <= 2)
  +                     break;
  +             wait_for_completion_interruptible_timeout(
  +                             &blkif->drain_complete, HZ);
  +
  +             if (!atomic_read(&blkif->drain))
  +                     break;
  +     } while (!kthread_should_stop());
  +     atomic_set(&blkif->drain, 0);
  +}
  +
   /*
    * Completion callback on the bio's. Called as bh->b_end_io()
    */
@@@@ -584,23 -581,22 -515,6 +581,23 @@@@ __do_block_io_op(struct xen_blkif *blki
        return more_to_do;
   }
   
  +static int
  +do_block_io_op(struct xen_blkif *blkif)
  +{
  +     union blkif_back_rings *blk_rings = &blkif->blk_rings;
  +     int more_to_do;
  +
  +     do {
  +             more_to_do = __do_block_io_op(blkif);
  +             if (more_to_do)
  +                     break;
  +
  +             RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
  +     } while (more_to_do);
  +
  +     return more_to_do;
  +}
 ++
   /*
    * Transmutation of the 'struct blkif_request' to a proper 'struct bio'
    * and call the 'submit_bio' to pass it to the underlying storage.
@@@@ -634,10 -630,6 -545,7 +631,6 @@@@ static int dispatch_rw_block_io(struct 
                blkif->st_f_req++;
                operation = WRITE_FLUSH;
                break;
-       case BLKIF_OP_DISCARD:
-               blkif->st_ds_req++;
-               operation = REQ_DISCARD;
-               break;
  -     case BLKIF_OP_WRITE_BARRIER:
        default:
                operation = 0; /* make gcc happy */
                goto fail_response;
        }
   
        /* Check that the number of segments is sane. */
- -     nseg = req->nr_segments;
-       if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
-                               operation != REQ_DISCARD) ||
+ +     nseg = req->u.rw.nr_segments;
+ +
+       if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
            unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
                pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
                         nseg);
         * the hypercall to unmap the grants - that is all done in
         * xen_blkbk_unmap.
         */
-       if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
+       if (xen_blkbk_map(req, pending_req, seg))
                goto fail_flush;
   
  -     /* This corresponding xen_blkif_put is done in __end_block_io_op */
  +     /*
  +      * This corresponding xen_blkif_put is done in __end_block_io_op, or
  +      * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
  +      */
        xen_blkif_get(blkif);
   
        for (i = 0; i < nseg; i++) {
                preq.sector_number += seg[i].nsec;
        }
   
  -     /* This will be hit if the operation was a flush. */
  +     /* This will be hit if the operation was a flush or discard. */
        if (!bio) {
-               BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
+               BUG_ON(operation != WRITE_FLUSH);
   
-               if (operation == WRITE_FLUSH) {
-                       bio = bio_alloc(GFP_KERNEL, 0);
-                       if (unlikely(bio == NULL))
-                               goto fail_put_bio;
+               bio = bio_alloc(GFP_KERNEL, 0);
+               if (unlikely(bio == NULL))
+                       goto fail_put_bio;
   
-                       biolist[nbio++] = bio;
-                       bio->bi_bdev    = preq.bdev;
-                       bio->bi_private = pending_req;
-                       bio->bi_end_io  = end_block_io_op;
-               } else if (operation == REQ_DISCARD) {
-                       xen_blk_discard(blkif, req);
-                       xen_blkif_put(blkif);
-                       free_req(pending_req);
-                       return 0;
-               }
+               biolist[nbio++] = bio;
+               bio->bi_bdev    = preq.bdev;
+               bio->bi_private = pending_req;
+               bio->bi_end_io  = end_block_io_op;
        }
   
        /*
index a6d43030b1078e027e4c0ccb41cea7070518e428,5b62f519cde579fa712ebcc04438350bb6c19a5f,6a381de39e6f10d840d54f217a11f6a3505b6f8a..187fd2c1a15d077cd8cf1c8f88877b3307f8a661
@@@@ -423,73 -386,82 -379,6 +386,82 @@@@ int xen_blkbk_flush_diskcache(struct xe
        return err;
   }
   
  +int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
  +{
  +     struct xenbus_device *dev = be->dev;
  +     struct xen_blkif *blkif = be->blkif;
  +     char *type;
  +     int err;
  +     int state = 0;
  +
  +     type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
  +     if (!IS_ERR(type)) {
  +             if (strncmp(type, "file", 4) == 0) {
  +                     state = 1;
  +                     blkif->blk_backend_type = BLKIF_BACKEND_FILE;
  +             }
  +             if (strncmp(type, "phy", 3) == 0) {
  +                     struct block_device *bdev = be->blkif->vbd.bdev;
  +                     struct request_queue *q = bdev_get_queue(bdev);
  +                     if (blk_queue_discard(q)) {
  +                             err = xenbus_printf(xbt, dev->nodename,
  +                                     "discard-granularity", "%u",
  +                                     q->limits.discard_granularity);
  +                             if (err) {
  +                                     xenbus_dev_fatal(dev, err,
  +                                             "writing discard-granularity");
  +                                     goto kfree;
  +                             }
  +                             err = xenbus_printf(xbt, dev->nodename,
  +                                     "discard-alignment", "%u",
  +                                     q->limits.discard_alignment);
  +                             if (err) {
  +                                     xenbus_dev_fatal(dev, err,
  +                                             "writing discard-alignment");
  +                                     goto kfree;
  +                             }
  +                             state = 1;
  +                             blkif->blk_backend_type = BLKIF_BACKEND_PHY;
  +                     }
+ +                     /* Optional. */
+ +                     err = xenbus_printf(xbt, dev->nodename,
+ +                             "discard-secure", "%d",
+ +                             blkif->vbd.discard_secure);
+ +                     if (err) {
+ +                             xenbus_dev_fatal(dev, err,
+ +                                     "writting discard-secure");
+ +                             goto kfree;
+ +                     }
  +             }
  +     } else {
  +             err = PTR_ERR(type);
  +             xenbus_dev_fatal(dev, err, "reading type");
  +             goto out;
  +     }
  +
  +     err = xenbus_printf(xbt, dev->nodename, "feature-discard",
  +                         "%d", state);
  +     if (err)
  +             xenbus_dev_fatal(dev, err, "writing feature-discard");
  +kfree:
  +     kfree(type);
  +out:
  +     return err;
  +}
  +int xen_blkbk_barrier(struct xenbus_transaction xbt,
  +                   struct backend_info *be, int state)
  +{
  +     struct xenbus_device *dev = be->dev;
  +     int err;
  +
  +     err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
  +                         "%d", state);
  +     if (err)
  +             xenbus_dev_fatal(dev, err, "writing feature-barrier");
  +
  +     return err;
  +}
  +
   /*
    * Entry point to this code when a new device is created.  Allocate the basic
    * structures, and watch the store waiting for the hotplug scripts to tell us
index 7b2ec5908413da7b989044828879afa173613b87,f3c45ba1304e505b0508246468b2a178be014f1e,b536a9cef917516d23448e589a7955ad984e6dd3..351ddeffd430bf094c2dc57e56020ca38476097b
@@@@ -98,9 -98,10 -98,6 +98,10 @@@@ struct blkfront_inf
        unsigned long shadow_free;
        unsigned int feature_flush;
        unsigned int flush_op;
-       unsigned int feature_discard;
+ +     unsigned int feature_discard:1;
+ +     unsigned int feature_secdiscard:1;
  +     unsigned int discard_granularity;
  +     unsigned int discard_alignment;
        int is_ready;
   };
   
@@@@ -305,36 -306,41 -302,29 +306,41 @@@@ static int blkif_queue_request(struct r
                ring_req->operation = info->flush_op;
        }
   
-       if (unlikely(req->cmd_flags & REQ_DISCARD)) {
  -     ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
  -     BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
  -
  -     for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
  -             buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
  -             fsect = sg->offset >> 9;
  -             lsect = fsect + (sg->length >> 9) - 1;
  -             /* install a grant reference. */
  -             ref = gnttab_claim_grant_reference(&gref_head);
  -             BUG_ON(ref == -ENOSPC);
  -
  -             gnttab_grant_foreign_access_ref(
  -                             ref,
  -                             info->xbdev->otherend_id,
  -                             buffer_mfn,
  -                             rq_data_dir(req) );
  -
  -             info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
  -             ring_req->u.rw.seg[i] =
  -                             (struct blkif_request_segment) {
  -                                     .gref       = ref,
  -                                     .first_sect = fsect,
  -                                     .last_sect  = lsect };
+ +     if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) {
  +             /* id, sector_number and handle are set above. */
  +             ring_req->operation = BLKIF_OP_DISCARD;
-               ring_req->nr_segments = 0;
  +             ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+ +             if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
+ +                     ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
+ +             else
+ +                     ring_req->u.discard.flag = 0;
  +     } else {
-               ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
-               BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ +             ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req,
+ +                                                        info->sg);
+ +             BUG_ON(ring_req->u.rw.nr_segments >
+ +                    BLKIF_MAX_SEGMENTS_PER_REQUEST);
  +
-               for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+ +             for_each_sg(info->sg, sg, ring_req->u.rw.nr_segments, i) {
  +                     buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
  +                     fsect = sg->offset >> 9;
  +                     lsect = fsect + (sg->length >> 9) - 1;
  +                     /* install a grant reference. */
  +                     ref = gnttab_claim_grant_reference(&gref_head);
  +                     BUG_ON(ref == -ENOSPC);
  +
  +                     gnttab_grant_foreign_access_ref(
  +                                     ref,
  +                                     info->xbdev->otherend_id,
  +                                     buffer_mfn,
  +                                     rq_data_dir(req));
  +
  +                     info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
  +                     ring_req->u.rw.seg[i] =
  +                                     (struct blkif_request_segment) {
  +                                             .gref       = ref,
  +                                             .first_sect = fsect,
  +                                             .last_sect  = lsect };
  +             }
        }
   
        info->ring.req_prod_pvt++;
@@@@ -419,13 -425,15 -406,6 +425,15 @@@@ static int xlvbd_init_blk_queue(struct 
   
        queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
   
  +     if (info->feature_discard) {
  +             queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, rq);
  +             blk_queue_max_discard_sectors(rq, get_capacity(gd));
  +             rq->limits.discard_granularity = info->discard_granularity;
  +             rq->limits.discard_alignment = info->discard_alignment;
+ +             if (info->feature_secdiscard)
+ +                     queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, rq);
  +     }
  +
        /* Hard sector size and max sectors impersonate the equiv. hardware. */
        blk_queue_logical_block_size(rq, sector_size);
        blk_queue_max_hw_sectors(rq, 512);
@@@@ -742,17 -753,19 -722,6 +753,19 @@@@ static irqreturn_t blkif_interrupt(int 
   
                error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
                switch (bret->operation) {
  +             case BLKIF_OP_DISCARD:
  +                     if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
  +                             struct request_queue *rq = info->rq;
  +                             printk(KERN_WARNING "blkfront: %s: discard op failed\n",
  +                                        info->gd->disk_name);
  +                             error = -EOPNOTSUPP;
  +                             info->feature_discard = 0;
+ +                             info->feature_secdiscard = 0;
  +                             queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+ +                             queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq);
  +                     }
  +                     __blk_end_request_all(req, error);
  +                     break;
                case BLKIF_OP_FLUSH_DISKCACHE:
                case BLKIF_OP_WRITE_BARRIER:
                        if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
@@@@ -1129,33 -1144,41 -1098,6 +1144,41 @@@@ blkfront_closing(struct blkfront_info *
        bdput(bdev);
   }
   
  +static void blkfront_setup_discard(struct blkfront_info *info)
  +{
  +     int err;
  +     char *type;
  +     unsigned int discard_granularity;
  +     unsigned int discard_alignment;
+ +     unsigned int discard_secure;
  +
  +     type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
  +     if (IS_ERR(type))
  +             return;
  +
+ +     info->feature_secdiscard = 0;
  +     if (strncmp(type, "phy", 3) == 0) {
  +             err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
  +                     "discard-granularity", "%u", &discard_granularity,
  +                     "discard-alignment", "%u", &discard_alignment,
  +                     NULL);
  +             if (!err) {
  +                     info->feature_discard = 1;
  +                     info->discard_granularity = discard_granularity;
  +                     info->discard_alignment = discard_alignment;
  +             }
+ +             err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ +                         "discard-secure", "%d", &discard_secure,
+ +                         NULL);
+ +             if (!err)
+ +                     info->feature_secdiscard = discard_secure;
+ +
  +     } else if (strncmp(type, "file", 4) == 0)
  +             info->feature_discard = 1;
  +
  +     kfree(type);
  +}
  +
   /*
    * Invoked when the backend is finally 'ready' (and has told produced
    * the details about the physical device - #sectors, size, etc).
Simple merge
Simple merge
diff --cc mm/vmalloc.c
Simple merge