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
|