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

Re: [Xen-devel] [PATCH v1 7/7] xen-block: implement indirect descriptors



> >> +struct blkif_x86_32_request_indirect {
> >> +     uint8_t        indirect_op;
> >> +     uint16_t       nr_segments;
> > 
> > This needs to be documented. Is there are limit to what it can be? What if
> > the frontend sets it to 1231231?
> 
> This is checked in dispatch_rw_block_io:
> 
> if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
>     unlikely((req->operation != BLKIF_OP_INDIRECT) &&
>              (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) ||
>     unlikely((req->operation == BLKIF_OP_INDIRECT) &&
>              (nseg > MAX_INDIRECT_SEGMENTS))) {
>       pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
>                nseg);

I am wondering whether we should make that pr_err ..?

>       /* Haven't submitted any bio's yet. */
>       goto fail_response;
> }
> 
> And the value of MAX_INDIRECT_SEGMENTS is exported to the frontend in
> xenstore, so the frontend does:
> 
> max_indirect_segments = min(MAX_INDIRECT_SEGMENTS, front_max_segments);
> 
> To know how many segments it can safely use in an indirect op.

<nods>
> 
> > 
> >> +     uint64_t       id;
> >> +     blkif_sector_t sector_number;
> >> +     blkif_vdev_t   handle;
> >> +     uint16_t       _pad1;
> >> +     grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_GREFS_PER_REQUEST];
> > 
> > And how do we figure out whether we are going to use one indirect_grefs or 
> > many?
> > That should be described here. (if I understand it right it would be done
> > via the maximum-indirect-something' variable)
> 
> I've added the following comment:
> 
> /*
>  * The maximum number of indirect segments (and pages) that will
>  * be used is determined by MAX_INDIRECT_SEGMENTS, this value
>  * is also exported to the guest (via xenstore max-indirect-segments
.. feature-max-indirect-segments..
>  * entry), so the frontend knows how many indirect segments the
>  * backend supports.
>  */
> 
Great!
> > 
> > 
> >> +} __attribute__((__packed__));
> >> +
> > 
> > Per my calculation the size of this structure is 55 bytes. The 64-bit is 59 
> > bytes.
> > 
> > It is a bit odd, but then 1 byte is for the 'operation' in the 
> > 'blkif_x*_request',
> > so it comes out to 56 and 60 bytes.
> > 
> > Is that still the right amount ? I thought we wanted to flesh it out to be 
> > a nice
> > 64 byte aligned so that the future patches which will make the requests be
> > more cache-aligned and won't have to play games?
> 
> Yes, I've added a uint32_t for 64bits and a uint64_t for 32bits, that
> makes it 64bytes aligned in both cases.

Thanks
> 
> > 
> >>  struct blkif_x86_32_request {
> >>       uint8_t        operation;    /* BLKIF_OP_???                         
> >> */
> >>       union {
> >>               struct blkif_x86_32_request_rw rw;
> >>               struct blkif_x86_32_request_discard discard;
> >>               struct blkif_x86_32_request_other other;
> >> +             struct blkif_x86_32_request_indirect indirect;
> >>       } u;
> >>  } __attribute__((__packed__));
> >>
> >> @@ -127,12 +149,24 @@ struct blkif_x86_64_request_other {
> >>       uint64_t       id;           /* private guest value, echoed in resp  
> >> */
> >>  } __attribute__((__packed__));
> >>
> >> +struct blkif_x86_64_request_indirect {
> >> +     uint8_t        indirect_op;
> >> +     uint16_t       nr_segments;
> >> +     uint32_t       _pad1; /* offsetof(blkif_..,u.indirect.id)==8   */
> > 
> > The comment is a bit off compared to the rest.
> > 
> >> +     uint64_t       id;
> >> +     blkif_sector_t sector_number;
> >> +     blkif_vdev_t   handle;
> >> +     uint16_t       _pad2;
> >> +     grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_GREFS_PER_REQUEST];
> >> +} __attribute__((__packed__));
> >> +
> >>  struct blkif_x86_64_request {
> >>       uint8_t        operation;    /* BLKIF_OP_???                         
> >> */
> >>       union {
> >>               struct blkif_x86_64_request_rw rw;
> >>               struct blkif_x86_64_request_discard discard;
> >>               struct blkif_x86_64_request_other other;
> >> +             struct blkif_x86_64_request_indirect indirect;
> >>       } u;
> >>  } __attribute__((__packed__));
> >>
> >> @@ -257,6 +291,11 @@ struct xen_blkif {
> >>       wait_queue_head_t       waiting_to_free;
> >>  };
> >>
> >> +struct seg_buf {
> >> +     unsigned long offset;
> >> +     unsigned int nsec;
> >> +};
> >> +
> >>  /*
> >>   * Each outstanding request that we've passed to the lower device layers 
> >> has a
> >>   * 'pending_req' allocated to it. Each buffer_head that completes 
> >> decrements
> >> @@ -271,9 +310,16 @@ struct pending_req {
> >>       unsigned short          operation;
> >>       int                     status;
> >>       struct list_head        free_list;
> >> -     struct page             *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
> >> -     struct persistent_gnt   
> >> *persistent_gnts[BLKIF_MAX_SEGMENTS_PER_REQUEST];
> >> -     grant_handle_t          
> >> grant_handles[BLKIF_MAX_SEGMENTS_PER_REQUEST];
> >> +     struct page             *pages[MAX_INDIRECT_SEGMENTS];
> >> +     struct persistent_gnt   *persistent_gnts[MAX_INDIRECT_SEGMENTS];
> >> +     grant_handle_t          grant_handles[MAX_INDIRECT_SEGMENTS];
> >> +     grant_ref_t             grefs[MAX_INDIRECT_SEGMENTS];
> >> +     /* Indirect descriptors */
> >> +     struct persistent_gnt   
> >> *indirect_persistent_gnts[MAX_INDIRECT_GREFS];
> >> +     struct page             *indirect_pages[MAX_INDIRECT_GREFS];
> >> +     grant_handle_t          indirect_handles[MAX_INDIRECT_GREFS];
> >> +     struct seg_buf          seg[MAX_INDIRECT_SEGMENTS];
> >> +     struct bio              *biolist[MAX_INDIRECT_SEGMENTS];
> > 
> > Oh wow. That is a big structure. So 1536 for the 
> > BLKIF_MAX_SEGMENTS_PER_REQUEST
> > ones and 24 bytes for the ones that deail with MAX_INDIRECT_GREFS.
> > 
> > This could be made look nicer. For example you could do:
> > 
> >         struct indirect {
> >                 struct page;
> >                 grant_handle_t handle;
> >                 struct persistent_gnt *gnt;
> >         } desc[MAX_INDIRECT_GREFS];
> > 
> >         .. and the same treatment to the BLKIF_MAX_SEGMENTS_PER_REQUEST
> > one.
> > 
> > Thought perhaps it makes more sense to do that with a later patch as a 
> > cleanup.
> 
> This was similar to what Jan was suggesting, but I would prefer to leave
> that for a latter patch.

<nods>

.. snip..
> >> +/*
> >> + * Maximum number of segments in indirect requests, the actual value used 
> >> by
> >> + * the frontend driver is the minimum of this value and the value provided
> >> + * by the backend driver.
> >> + */
> >> +
> >> +static int xen_blkif_max_segments = 32;
> >> +module_param_named(max_segments, xen_blkif_max_segments, int, 0);
> >> +MODULE_PARM_DESC(max_segments,
> >> +"Maximum number of segments in indirect requests");
> > 
> > This means a new entry in Documentation/ABI/sysfs/...
> 
> I think I should just not allow this to be exported, since we cannot
> change it at run-time, so if a user changes the 0 to something else, and
> changes the value... nothing will happen (because this is only used
> before the device is connected).

OK, lets then not make it a module_param_named.

> 
> > 
> > Perhaps the xen-blkfront part of the patch should be just split out to make
> > this easier?
> > 
> > Perhaps what we really should have is just the 'max' value of megabytes
> > we want to handle on the ring.
> > 
> > As right now 32 ring requests * 32 segments = 4MB.  But if the user wants
> > to se the max: 32 * 4096 = so 512MB (right? each request would handle now 
> > 16MB
> > and since we have 32 of them = 512MB).
> 
> I've just set that to something that brings a performance benefit
> without having to map an insane number of persistent grants in blkback.
> 
> Yes, the values are correct, but the device request queue (rq) is only
> able to provide read requests with 64 segments or write requests with
> 128 segments. I haven't been able to get larger requests, even when
> setting this to 512 or higer.

What are you using to drive the requests? 'fio'?

.. snip..
> >> @@ -588,13 +666,14 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, 
> >> u16 sector_size)
> >>  static void xlvbd_flush(struct blkfront_info *info)
> >>  {
> >>       blk_queue_flush(info->rq, info->feature_flush);
> >> -     printk(KERN_INFO "blkfront: %s: %s: %s %s\n",
> >> +     printk(KERN_INFO "blkfront: %s: %s: %s %s %s\n",
> >>              info->gd->disk_name,
> >>              info->flush_op == BLKIF_OP_WRITE_BARRIER ?
> >>               "barrier" : (info->flush_op == BLKIF_OP_FLUSH_DISKCACHE ?
> >>               "flush diskcache" : "barrier or flush"),
> >>              info->feature_flush ? "enabled" : "disabled",
> >> -            info->feature_persistent ? "using persistent grants" : "");
> >> +            info->feature_persistent ? "using persistent grants" : "",
> >> +            info->max_indirect_segments ? "using indirect descriptors" : 
> >> "");
> > 
> > This is a bit of mess now:
> > 
> > 
> > [    0.968241] blkfront: xvda: barrier or flush: disabled using persistent 
> > grants using indirect descriptors
> > 
> > Should it just be:
> > 
> > 'persistent_grants: enabled; indirect descriptors: enabled'
> > 
> > ?
> 
> Agreed. If you don't mind I will change the wording for both persistent
> grants and indirect descriptors in this same patch.

That is OK.

.. snip..
> >>   * Invoked when the backend is finally 'ready' (and has told produced
> >>   * the details about the physical device - #sectors, size, etc).
> >> @@ -1414,8 +1735,9 @@ static void blkfront_connect(struct blkfront_info 
> >> *info)
> >>               set_capacity(info->gd, sectors);
> >>               revalidate_disk(info->gd);
> >>
> >> -             /* fall through */
> >> +             return;
> > 
> > How come?
> 
> We cannot fall thought anymore, because now we call blkif_recover in
> order to recover after performing the suspension, in the past this was
> just a return so we could fall thought.
> 
> We need to perform the recover at this point because we need to know if
> the backend supports indirect descriptors, and how many. In the past we
> used to perform the recover before the backend announced it's features,
> but now we need to know if the backend supports indirect segments or not.

OK. Can you put that nice explanation as a comment in there please?

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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