[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/2] make blkback driver handle trim request
>>> On 09.08.11 at 09:11, Li Dongyang <lidongyang@xxxxxxxxxx> wrote: > 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. Same general comments as for the frontend patch, plus ... > 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) static? > +{ > + 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 These two constants are being used only internally to the driver, so they shouldn't become part of the interface (and you then also shouldn't merge them into a variable that is used for interface defined flags). Jan > > #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |