xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Roger Pau Monne <roger.pau@citrix.com>
Cc: "xen-devel@lists.xenproject.org" <xen-devel@lists.xenproject.org>,
	Jan Beulich <jbeulich@suse.com>,
	Andrew Cooper <Andrew.Cooper3@citrix.com>
Subject: Re: [PATCH v3 08/12] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list
Date: Tue, 5 Sep 2017 09:06:11 +0000	[thread overview]
Message-ID: <cc6966b3100b4d67a25d8caea3a5449a@AMSPEX02CL03.citrite.net> (raw)
In-Reply-To: <20170904134047.4eychido47muojyy@MacBook-Pro-de-Roger.local>

> -----Original Message-----
> From: Roger Pau Monne
> Sent: 04 September 2017 14:41
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: xen-devel@lists.xenproject.org; Andrew Cooper
> <Andrew.Cooper3@citrix.com>; Jan Beulich <jbeulich@suse.com>
> Subject: Re: [Xen-devel] [PATCH v3 08/12] x86/hvm/ioreq: maintain an array
> of ioreq servers rather than a list
> 
> On Thu, Aug 31, 2017 at 10:36:01AM +0100, Paul Durrant wrote:
> > A subsequent patch will remove the current implicit limitation on creation
> > of ioreq servers which is due to the allocation of gfns for the ioreq
> > structures and buffered ioreq ring.
> >
> > It will therefore be necessary to introduce an explicit limit and, since
> > this limit should be small, it simplifies the code to maintain an array of
> > that size rather than using a list.
> >
> > Also, by reserving an array slot for the default server and populating
> > array slots early in create, the need to pass an 'is_default' boolean
> > to sub-functions can be avoided.
> >
> > Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> > ---
> > Cc: Jan Beulich <jbeulich@suse.com>
> > Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> >
> > v3:
> >  - New patch (replacing "move is_default into struct hvm_ioreq_server") in
> >    response to review comments.
> > ---
> >  xen/arch/x86/hvm/ioreq.c         | 507 +++++++++++++++++++----------------
> ----
> >  xen/include/asm-x86/hvm/domain.h |  11 +-
> >  2 files changed, 247 insertions(+), 271 deletions(-)
> >
> > diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
> > index 5e01e1a6d2..0e92763384 100644
> > --- a/xen/arch/x86/hvm/ioreq.c
> > +++ b/xen/arch/x86/hvm/ioreq.c
> > @@ -46,14 +46,18 @@ static ioreq_t *get_ioreq(struct hvm_ioreq_server
> *s, struct vcpu *v)
> >  bool hvm_io_pending(struct vcpu *v)
> >  {
> >      struct domain *d = v->domain;
> > -    struct hvm_ioreq_server *s;
> > +    unsigned int id;
> >
> > -    list_for_each_entry ( s,
> > -                          &d->arch.hvm_domain.ioreq_server.list,
> > -                          list_entry )
> > +    for ( id = 0; id < MAX_NR_IOREQ_SERVERS; id++ )
> >      {
> > +        struct hvm_ioreq_server *s;
> >          struct hvm_ioreq_vcpu *sv;
> >
> > +        s = d->arch.hvm_domain.ioreq_server.server[id];
> > +
> 
> No need for the extra newline IMHO (here and below). You could also
> do the initialization together with the definition, but I guess that's
> going to exceed the line char limit?
> 
> Or even you could do something like this AFAICT:
> 
> for ( id = 0, s = d->arch.hvm_domain.ioreq_server.server[0];
>       id < MAX_NR_IOREQ_SERVERS;
>       id++, s = d->arch.hvm_domain.ioreq_server.server[id] )
> {
>      ....
> 
> I would make this a macro (FOREACH_IOREQ_SERVER or similar), since the
> pattern seems to be repeated in quite a lot of places.

Yes, that's probably a good plan. I'll look at doing that.

> 
> > +#define IS_DEFAULT(s) \
> > +    (s == s->domain-
> >arch.hvm_domain.ioreq_server.server[DEFAULT_IOSERVID])
> 
> Parentheses around the instances of s please.

Indeed. Missed that.

> 
> >  static int hvm_ioreq_server_alloc_rangesets(struct hvm_ioreq_server *s,
> > -                                            bool is_default)
> > +                                            ioservid_t id)
> 
> You could get the id by doing some arithmetic with the array and s,
> but I don't think that's worth it.
> 

No, I can't anyway because the array contains pointers not the structs themselves.

> >  int hvm_create_ioreq_server(struct domain *d, domid_t domid,
> > @@ -685,52 +667,66 @@ int hvm_create_ioreq_server(struct domain *d,
> domid_t domid,
> >                              ioservid_t *id)
> >  {
> >      struct hvm_ioreq_server *s;
> > +    unsigned int i;
> >      int rc;
> >
> >      if ( bufioreq_handling > HVM_IOREQSRV_BUFIOREQ_ATOMIC )
> >          return -EINVAL;
> >
> > -    rc = -ENOMEM;
> >      s = xzalloc(struct hvm_ioreq_server);
> >      if ( !s )
> > -        goto fail1;
> > +        return -ENOMEM;
> >
> >      domain_pause(d);
> >      spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> >
> > -    rc = -EEXIST;
> > -    if ( is_default && d->arch.hvm_domain.default_ioreq_server != NULL )
> > -        goto fail2;
> > -
> > -    rc = hvm_ioreq_server_init(s, d, domid, is_default, bufioreq_handling,
> > -                               next_ioservid(d));
> > -    if ( rc )
> > -        goto fail3;
> > -
> > -    list_add(&s->list_entry,
> > -             &d->arch.hvm_domain.ioreq_server.list);
> > -
> >      if ( is_default )
> >      {
> > -        d->arch.hvm_domain.default_ioreq_server = s;
> > -        hvm_ioreq_server_enable(s, true);
> > +        i = DEFAULT_IOSERVID;
> > +
> > +        rc = -EEXIST;
> > +        if ( d->arch.hvm_domain.ioreq_server.server[i] )
> > +            goto fail;
> > +    }
> > +    else
> > +    {
> > +        for ( i = 0; i < MAX_NR_IOREQ_SERVERS; i++ )
> > +        {
> > +            if ( i != DEFAULT_IOSERVID &&
> > +                 !d->arch.hvm_domain.ioreq_server.server[i] )
> > +                break;
> > +        }
> > +
> > +        rc = -ENOSPC;
> > +        if ( i >= MAX_NR_IOREQ_SERVERS )
> > +            goto fail;
> >      }
> >
> > +    d->arch.hvm_domain.ioreq_server.server[i] = s;
> > +
> > +    rc = hvm_ioreq_server_init(s, d, domid, bufioreq_handling, i);
> > +    if ( rc )
> > +        goto fail;
> > +
> > +    if ( IS_DEFAULT(s) )
> > +        hvm_ioreq_server_enable(s);
> > +
> >      if ( id )
> > -        *id = s->id;
> > +        *id = i;
> > +
> > +    d->arch.hvm_domain.ioreq_server.count++;
> >
> >      spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> >      domain_unpause(d);
> >
> >      return 0;
> >
> > - fail3:
> > - fail2:
> > + fail:
> >      spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> >      domain_unpause(d);
> >
> > +    d->arch.hvm_domain.ioreq_server.server[i] = NULL;
> 
> Shouldn't this be done while holding the ioreq_server lock?
> 

Yes, it should.

> >      xfree(s);
> > - fail1:
> >      return rc;
> >  }
> >
> > @@ -741,35 +737,30 @@ int hvm_destroy_ioreq_server(struct domain *d,
> ioservid_t id)
> >
> >      spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> >
> > -    rc = -ENOENT;
> > -    list_for_each_entry ( s,
> > -                          &d->arch.hvm_domain.ioreq_server.list,
> > -                          list_entry )
> > -    {
> > -        if ( s == d->arch.hvm_domain.default_ioreq_server )
> > -            continue;
> > +    s = d->arch.hvm_domain.ioreq_server.server[id];
> >
> > -        if ( s->id != id )
> > -            continue;
> > -
> > -        domain_pause(d);
> > +    rc = -ENOENT;
> > +    if ( id >= MAX_NR_IOREQ_SERVERS || !s || IS_DEFAULT(s) )
> 
> The id >= MAX_NR_IOREQ_SERVERS should be done before getting the
> element IMHO, even before getting the lock.

Ok, if you prefer.

> 
> Also, I don't like the:
> 
> rc = ...
> if ( ... )
>     goto error
> 
> construct, I think it's easy to make a mistake and end up returning an
> error code in the successful path (or forgetting to set an error when
> needed). This is however widely used in Xen, so I'm not going to
> complain any more.

It's a construct I tend to use as, in my experience (although I have not checked with recent versions of gcc) it leads to smaller code. If you use:

If (theres-an-error)
{
  rc = -errno;
  goto error;
}

then this will probably generate (in pseudo-assembly):

test theres-an-error
jump-if false 1f
move -errno, rc
jump error
1: ...

whereas using:

rc = -errno;
if (theres-an-error)
  goto error;

will probably generate something like:

move -errno, rc
test theres-an-error
jump-if true error

which IMO is more efficient and easier to read.

> 
> >  void hvm_destroy_all_ioreq_servers(struct domain *d)
> >  {
> > -    struct hvm_ioreq_server *s, *next;
> > +    unsigned int id;
> >
> >      spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> >
> >      /* No need to domain_pause() as the domain is being torn down */
> >
> > -    list_for_each_entry_safe ( s,
> > -                               next,
> > -                               &d->arch.hvm_domain.ioreq_server.list,
> > -                               list_entry )
> > +    for ( id = 0; id < MAX_NR_IOREQ_SERVERS; id++ )
> >      {
> > -        bool is_default = (s == d->arch.hvm_domain.default_ioreq_server);
> > +        struct hvm_ioreq_server *s;
> >
> > -        hvm_ioreq_server_disable(s, is_default);
> > +        s = d->arch.hvm_domain.ioreq_server.server[id];
> >
> > -        if ( is_default )
> > -            d->arch.hvm_domain.default_ioreq_server = NULL;
> > +        if ( !s )
> > +            continue;
> >
> > -        list_del(&s->list_entry);
> > +        hvm_ioreq_server_disable(s);
> > +        hvm_ioreq_server_deinit(s);
> >
> > -        hvm_ioreq_server_deinit(s, is_default);
> > +        ASSERT(d->arch.hvm_domain.ioreq_server.count);
> > +        --d->arch.hvm_domain.ioreq_server.count;
> 
> It seems more common to use d->arch.hvm_domain.ioreq_server.count--,
> unless there' a reason for prefixing the decrement.

That's habit from the days of the 68000 which had a predecrement-and-indirect addressing mode so using predecrement generally yielded smaller code :-) I still prefer it. Postdecrement just looks odd to me.

> > +#define MAX_NR_IOREQ_SERVERS 8
> > +#define DEFAULT_IOSERVID 0
> 
> I would rather write it as DEFAULT_IOREQ_ID or DEFAULT_IOSERVER_ID I
> don't think there's any need to shorten SERVER here (specially when
> it's not shorted in MAX_NR_IOREQ_SERVERS.
> 

I named it after the ioservid_t type. I'd prefer to keep it that way.

Cheers,

  Paul

> Thanks, Roger.

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

  parent reply	other threads:[~2017-09-05  9:06 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-31  9:35 [PATCH v3 00/12] x86: guest resource mapping Paul Durrant
2017-08-31  9:35 ` [PATCH v3 01/12] x86/mm: allow a privileged PV domain to map guest mfns Paul Durrant
2017-08-31  9:35 ` [PATCH v3 02/12] x86/mm: add HYPERVISOR_memory_op to acquire guest resources Paul Durrant
2017-08-31  9:35 ` [PATCH v3 03/12] tools/libxenforeignmemory: add support for resource mapping Paul Durrant
2017-09-04 10:43   ` Roger Pau Monné
2017-09-04 15:38     ` Paul Durrant
2017-08-31  9:35 ` [PATCH v3 04/12] tools/libxenforeignmemory: reduce xenforeignmemory_restrict code footprint Paul Durrant
2017-09-04 10:47   ` Roger Pau Monné
2017-09-05  8:39     ` Paul Durrant
2017-08-31  9:35 ` [PATCH v3 05/12] tools/libxenctrl: use new xenforeignmemory API to seed grant table Paul Durrant
2017-09-04 11:05   ` Roger Pau Monné
2017-08-31  9:35 ` [PATCH v3 06/12] x86/hvm/ioreq: rename .*pfn and .*gmfn to .*gfn Paul Durrant
2017-08-31  9:36 ` [PATCH v3 07/12] x86/hvm/ioreq: use bool rather than bool_t Paul Durrant
2017-08-31  9:36 ` [PATCH v3 08/12] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list Paul Durrant
2017-09-04 13:40   ` Roger Pau Monné
2017-09-04 14:39     ` Jan Beulich
2017-09-05  9:06     ` Paul Durrant [this message]
2017-08-31  9:36 ` [PATCH v3 09/12] x86/hvm/ioreq: simplify code and use consistent naming Paul Durrant
2017-09-04 14:08   ` Roger Pau Monné
2017-08-31  9:36 ` [PATCH v3 10/12] x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page Paul Durrant
2017-08-31  9:36 ` [PATCH v3 11/12] x86/hvm/ioreq: defer mapping gfns until they are actually requsted Paul Durrant
2017-09-04 14:31   ` Roger Pau Monné
2017-08-31  9:36 ` [PATCH v3 12/12] x86/hvm/ioreq: add a new mappable resource type Paul Durrant
2017-09-04 15:02   ` Roger Pau Monné
2017-09-04 15:04     ` Paul Durrant

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cc6966b3100b4d67a25d8caea3a5449a@AMSPEX02CL03.citrite.net \
    --to=paul.durrant@citrix.com \
    --cc=Andrew.Cooper3@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=roger.pau@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).