[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/2] make blkback driver handle trim request



now blkback driver can handle the trim request from guest, we will
forward the request to phy if it's really a device has trim, or we'll
punch a hole on the image file.

Signed-off-by: Li Dongyang <lidongyang@xxxxxxxxxx>
---
 drivers/xen/blkback/blkback.c    |   77 ++++++++++++++++++++++++++++++++++++++
 drivers/xen/blkback/common.h     |    2 +-
 drivers/xen/blkback/xenbus.c     |   57 ++++++++++++++++++++++++++++
 include/xen/interface/io/blkif.h |    2 +
 4 files changed, 137 insertions(+), 1 deletions(-)

diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
index bb588e2..11aa09d 100644
--- a/drivers/xen/blkback/blkback.c
+++ b/drivers/xen/blkback/blkback.c
@@ -40,6 +40,9 @@
 #include <linux/freezer.h>
 #include <linux/list.h>
 #include <linux/delay.h>
+#include <linux/loop.h>
+#include <linux/falloc.h>
+#include <linux/fs.h>
 #include <xen/balloon.h>
 #include <xen/evtchn.h>
 #include <xen/gnttab.h>
@@ -112,6 +115,9 @@ static int do_block_io_op(blkif_t *blkif);
 static void dispatch_rw_block_io(blkif_t *blkif,
                                 blkif_request_t *req,
                                 pending_req_t *pending_req);
+static void dispatch_trim(blkif_t *blkif,
+                         blkif_request_trim_t *req,
+                         pending_req_t *pending_req);
 static void make_response(blkif_t *blkif, u64 id,
                          unsigned short op, int st);
 
@@ -369,6 +375,9 @@ static int do_block_io_op(blkif_t *blkif)
                        blkif->st_wr_req++;
                        dispatch_rw_block_io(blkif, &req, pending_req);
                        break;
+               case BLKIF_OP_TRIM:
+                       dispatch_trim(blkif, (blkif_request_trim_t *)&req, 
pending_req);
+                       break;
                case BLKIF_OP_PACKET:
                        DPRINTK("error: block operation BLKIF_OP_PACKET not 
implemented\n");
                        blkif->st_pk_req++;
@@ -395,6 +404,74 @@ static int do_block_io_op(blkif_t *blkif)
        return more_to_do;
 }
 
+static void dispatch_trim(blkif_t *blkif,
+                         blkif_request_trim_t *req,
+                         pending_req_t *pending_req)
+{
+       struct phys_req preq;
+       struct block_device *bdev = blkif->vbd.bdev;
+       int status = BLKIF_RSP_OKAY;
+       int err = 0;
+
+       preq.dev           = req->handle;
+       preq.sector_number = req->sector_number;
+       preq.nr_sects      = req->nr_sectors;
+
+       blkif_get(blkif);
+       if (blkif->vbd.type & VDISK_PHY_BACKEND) {
+               /* backend is a phy device, just forward the trim request */
+               if (vbd_translate(&preq, blkif, WRITE) != 0) {
+                       DPRINTK("access denied: %s of [%llu,%llu] on 
dev=%04x\n",
+                               "discard",
+                               preq.sector_number,
+                               preq.sector_number + preq.nr_sects, preq.dev);
+                       status = BLKIF_RSP_ERROR;
+                       goto fail_response;
+               }
+               err = blkdev_issue_discard(bdev,
+                                          req->sector_number,
+                                          req->nr_sectors,
+                                          GFP_KERNEL, 0);
+       } else if (blkif->vbd.type & VDISK_FILE_BACKEND) {
+               /* backend is a file, punch a hole in the file */
+               struct loop_device *lo = bdev->bd_disk->private_data;
+               struct file *file = lo->lo_backing_file;
+               struct inode *inode = file->f_path.dentry->d_inode;
+               if (vbd_translate(&preq, blkif, WRITE) != 0) {
+                       DPRINTK("access denied: %s of [%llu,%llu] on 
dev=%04x\n",
+                               "discard",
+                               preq.sector_number,
+                               preq.sector_number + preq.nr_sects, preq.dev);
+                       status = BLKIF_RSP_ERROR;
+                       goto fail_response;
+               }
+               if (inode->i_op->fallocate) {
+                       err = inode->i_op->fallocate(inode,
+                                  FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+                                  req->sector_number << 9,
+                                  req->nr_sectors << 9);
+               } else
+                       err = -EOPNOTSUPP;
+       } else {
+               status = BLKIF_RSP_EOPNOTSUPP;
+               goto fail_response;
+       }
+
+       if (err == -EOPNOTSUPP) {
+               DPRINTK("blkback: discard op failed, not supported\n");
+               status = BLKIF_RSP_EOPNOTSUPP;
+       } else if (err)
+               status = BLKIF_RSP_ERROR;
+
+fail_response:
+       make_response(blkif, req->id, req->operation, status);
+       blkif_put(blkif);
+       free_req(pending_req);
+       if (status)
+               msleep(1); /* back off a bit */
+       return;
+}
+
 static void dispatch_rw_block_io(blkif_t *blkif,
                                 blkif_request_t *req,
                                 pending_req_t *pending_req)
diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h
index 7ac10df..8423fd9 100644
--- a/drivers/xen/blkback/common.h
+++ b/drivers/xen/blkback/common.h
@@ -126,7 +126,7 @@ unsigned long vbd_secsize(struct vbd *vbd);
 
 struct phys_req {
        unsigned short       dev;
-       unsigned short       nr_sects;
+       blkif_sector_t       nr_sects;
        struct block_device *bdev;
        blkif_sector_t       sector_number;
 };
diff --git a/drivers/xen/blkback/xenbus.c b/drivers/xen/blkback/xenbus.c
index 639146c..d379fc8 100644
--- a/drivers/xen/blkback/xenbus.c
+++ b/drivers/xen/blkback/xenbus.c
@@ -219,6 +219,59 @@ int blkback_barrier(struct xenbus_transaction xbt,
        return err;
 }
 
+int blkback_discard(struct xenbus_transaction xbt, struct backend_info *be)
+{
+       struct xenbus_device *dev = be->dev;
+       struct vbd *vbd = &be->blkif->vbd;
+       char *type;
+       int err;
+       int state = 0;
+
+       type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
+       if (!IS_ERR(type)) {
+               if (strcmp(type, "file") == 0)
+                       state = 1;
+                       vbd->type |= VDISK_FILE_BACKEND;
+               if (strcmp(type, "phy") == 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;
+                               vbd->type |= VDISK_PHY_BACKEND;
+                       }
+               }
+       } 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;
+}
+
 /**
  * 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
@@ -444,6 +497,10 @@ again:
        if (err)
                goto abort;
 
+       err = blkback_discard(xbt, be);
+       if (err)
+               goto abort;
+
        err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
                            vbd_size(&be->blkif->vbd));
        if (err) {
diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h
index e239060..aa483cc 100644
--- a/include/xen/interface/io/blkif.h
+++ b/include/xen/interface/io/blkif.h
@@ -172,5 +172,7 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct 
blkif_response);
 #define VDISK_CDROM        0x1
 #define VDISK_REMOVABLE    0x2
 #define VDISK_READONLY     0x4
+#define VDISK_FILE_BACKEND 0x8
+#define VDISK_PHY_BACKEND  0x10
 
 #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
-- 
1.7.6


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.