[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


 


Rackspace

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