qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Marcel Apfelbaum <marcel.a@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: John Snow <jsnow@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [RFC v2 2/3] Add units-per-idebus property
Date: Sun, 21 Sep 2014 12:34:14 +0300	[thread overview]
Message-ID: <1411292054.3666.78.camel@localhost.localdomain> (raw)
In-Reply-To: <87mw9wq79a.fsf@blackfin.pond.sub.org>

On Fri, 2014-09-19 at 11:39 +0200, Markus Armbruster wrote:
> John Snow <jsnow@redhat.com> writes:
> 
> > Signed-off-by: John Snow <jsnow@redhat.com>
> > ---
> >  blockdev.c                | 10 ++++++++--
> >  device-hotplug.c          |  2 +-
> >  hw/i386/pc_q35.c          |  3 ++-
> >  include/hw/boards.h       |  3 ++-
> >  include/sysemu/blockdev.h |  2 +-
> >  vl.c                      | 19 +++++++++++--------
> >  6 files changed, 25 insertions(+), 14 deletions(-)
> >
> > diff --git a/blockdev.c b/blockdev.c
> > index 5e7c93a..6c524b7 100644
> > --- a/blockdev.c
> > +++ b/blockdev.c
> > @@ -45,6 +45,7 @@
> >  #include "qmp-commands.h"
> >  #include "trace.h"
> >  #include "sysemu/arch_init.h"
> > +#include "hw/boards.h"
> >  
> >  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
> >  
> > @@ -643,7 +644,7 @@ QemuOptsList qemu_legacy_drive_opts = {
> >      },
> >  };
> >  
> > -DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
> > +DriveInfo *drive_new(QemuOpts *all_opts, MachineClass *mc)
> >  {
> >      const char *value;
> >      DriveInfo *dinfo = NULL;
> > @@ -651,6 +652,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
> >      QemuOpts *legacy_opts;
> >      DriveMediaType media = MEDIA_DISK;
> >      BlockInterfaceType type;
> > +    BlockInterfaceType block_default_type = mc->block_default_type;
> >      int cyls, heads, secs, translation;
> >      int max_devs, bus_id, unit_id, index;
> >      const char *devaddr;
> > @@ -828,7 +830,11 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
> >      unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
> >      index   = qemu_opt_get_number(legacy_opts, "index", -1);
> >  
> > -    max_devs = if_max_devs[type];
> > +    if (type == IF_IDE && mc->units_per_idebus) {
> > +        max_devs = mc->units_per_idebus;
> > +    } else {
> > +        max_devs = if_max_devs[type];
> > +    }
> 
> This overrides if_max_devs[IF_IDE] in one out of three places.
> 
> if_max_devs[type] governs the mapping between index and (bus, unit).
> 
> If it's zero, then (bus, unit) = (0, index).
> 
> Else, (bus, unit) = (index / max_devs, index % max_devs).
> 
> Overriding it just here affects these things:
> 
> * Picking a default when the user specifies neither index nor unit
> 
> * Range checking unit
> 
> * Default ID, but let's ignore that for now
> 
> It does *not* affect drive_index_to_bus_id(), drive_index_to_unit_id(),
> i.e. the actual mapping between index and (bus, unit)!  index=1 is still
> mapped to (bus, unit) = (0, 1).  No good.
> 
> Testing (needs an incremental fix, see below) confirms:
> 
>     qemu: -drive if=ide,media=cdrom,index=1: unit 1 too big (max is 0)
> 
> You have to override if_max_devs[] consistently.
> 
> You provide for overriding if_max_devs[IF_IDE] only.  It'll do for now.
> 
> >  
> >      if (index != -1) {
> >          if (bus_id != 0 || unit_id != -1) {
> > diff --git a/device-hotplug.c b/device-hotplug.c
> > index e6a1ffb..857ac53 100644
> > --- a/device-hotplug.c
> > +++ b/device-hotplug.c
> > @@ -40,7 +40,7 @@ DriveInfo *add_init_drive(const char *optstr)
> >          return NULL;
> >  
> >      mc = MACHINE_GET_CLASS(current_machine);
> > -    dinfo = drive_new(opts, mc->block_default_type);
> > +    dinfo = drive_new(opts, mc);
> >      if (!dinfo) {
> >          qemu_opts_del(opts);
> >          return NULL;
> > diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> > index d4a907c..fd26fe1 100644
> > --- a/hw/i386/pc_q35.c
> > +++ b/hw/i386/pc_q35.c
> > @@ -348,7 +348,8 @@ static void pc_q35_init_1_4(MachineState *machine)
> >  
> >  #define PC_Q35_2_2_MACHINE_OPTIONS                      \
> >      PC_Q35_MACHINE_OPTIONS,                             \
> > -    .default_machine_opts = "firmware=bios-256k.bin"
> > +    .default_machine_opts = "firmware=bios-256k.bin",   \
> > +    .units_per_idebus = 1
> >  
> 
> I figrue this keeps -drive if=ide for older Q35 machines compatibly
> broken.  If that's what we want to do...
> 
> >  static QEMUMachine pc_q35_machine_v2_2 = {
> >      PC_Q35_2_2_MACHINE_OPTIONS,
> > diff --git a/include/hw/boards.h b/include/hw/boards.h
> > index dfb6718..73e656f 100644
> > --- a/include/hw/boards.h
> > +++ b/include/hw/boards.h
> > @@ -37,6 +37,7 @@ struct QEMUMachine {
> >          no_cdrom:1,
> >          no_sdcard:1;
> >      int is_default;
> > +    unsigned short units_per_idebus;
> >      const char *default_machine_opts;
> >      const char *default_boot_order;
> >      GlobalProperty *compat_props;
> 
> if_max_devs[] and the max_devs variables are all int.  I'd rather not
> mix signed and unsigned without need
> 
> > @@ -95,11 +96,11 @@ struct MachineClass {
> >          no_cdrom:1,
> >          no_sdcard:1;
> >      int is_default;
> > +    unsigned short units_per_idebus;
> >      const char *default_machine_opts;
> >      const char *default_boot_order;
> >      GlobalProperty *compat_props;
> >      const char *hw_version;
> > -
> >      HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
> >                                             DeviceState *dev);
> >  };
> 
> Let's keep the blank line separating the instance variables from the
> method.
> 
> > diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
> > index 25d52d2..f7de0a0 100644
> > --- a/include/sysemu/blockdev.h
> > +++ b/include/sysemu/blockdev.h
> > @@ -55,7 +55,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
> >  QemuOpts *drive_def(const char *optstr);
> >  QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
> >                      const char *optstr);
> > -DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
> > +DriveInfo *drive_new(QemuOpts *arg, MachineClass *mc);
> >  void drive_del(DriveInfo *dinfo);
> >  
> >  /* device-hotplug */
> > diff --git a/vl.c b/vl.c
> > index e095bcd..8359469 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -1151,9 +1151,9 @@ static int cleanup_add_fd(QemuOpts *opts, void *opaque)
> >  
> >  static int drive_init_func(QemuOpts *opts, void *opaque)
> >  {
> > -    BlockInterfaceType *block_default_type = opaque;
> > +    MachineClass *mc = opaque;
> >  
> > -    return drive_new(opts, *block_default_type) == NULL;
> > +    return drive_new(opts, mc) == NULL;
> >  }
> >  
> >  static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
> > @@ -1165,7 +1165,7 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
> >  }
> >  
> >  static void default_drive(int enable, int snapshot, BlockInterfaceType type,
> > -                          int index, const char *optstr)
> > +                          int index, const char *optstr, MachineClass *mc)
> >  {
> >      QemuOpts *opts;
> >  
> > @@ -1177,7 +1177,8 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type,
> >      if (snapshot) {
> >          drive_enable_snapshot(opts, NULL);
> >      }
> > -    if (!drive_new(opts, type)) {
> > +
> > +    if (!drive_new(opts, mc)) {
> >          exit(1);
> >      }
> >  }
> > @@ -1583,6 +1584,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
> >      mc->hot_add_cpu = qm->hot_add_cpu;
> >      mc->kvm_type = qm->kvm_type;
> >      mc->block_default_type = qm->block_default_type;
> > +    mc->units_per_idebus = qm->units_per_idebus;
> >      mc->max_cpus = qm->max_cpus;
> >      mc->no_serial = qm->no_serial;
> >      mc->no_parallel = qm->no_parallel;
> 
> Not sufficient!  You missed the duplicated code in
> pc_generic_machine_class_init().  That something was missing was quite
> obvious in my testing, although what was missing was not.  This is the
> fix I mentioned above.
> 
> Marcel, you touched both copies recently.  Do you know why we need two
> of them?  And why do we copy from QEMUMachine to MachineClass member by
> member?  Why can't we just point from MachineClass to QEMUMachine?  Or
> at least embed the struct so we can copy it wholesale?
Hi Markus,

I'll try to explain the design:
1. MachineClass should not be aware of QEMUMachine. The objective here is to
   eliminate QEMUMachine and it should not be part of MachineClass at any cost.
2. The plan is like this:
   - The machine types that are not yet QOMified will be QOMified on the fly
     by qemu_register_machine (vl.c) that calls machine_class_init and matches
     QEMUMachine fields with MachineClass fields.
     - This mechanism will be removed when all machines are QOMified. (never? :) )
   - Machines that are QOMified will not reach this code at all, but follow
     the normal QOM path.
As you can see, by design there is no duplication.

Now let's get to PC machines case:
- This is a "weird" use case of hybrid QOMifying.
- All that the author wanted was to have all the PC machines
  derive from type TYPE_PC_MACHINE, but didn't have the time/resources/will
  to go over every PC machine and QOMify it. But he did need the common class.
- His implementation:
  - He couldn't use the generic qemu_register_machine because the PC machines
    would not have derived from MACHINE_PC_TYPE.
  - So he used the following logic:
    - from the vl.c point of view, the PC machines are QOMified, so the
      PC machines registration *does not reach vl.c".
    - from the PC machines point of view, they remained not QOMified.
    - qemu_register_pc_machine mimics vl.c registration *only for pc machines*
      and has to copy the fields by itself. Plus, it gives the PC machines a common
      base class, the thing he was interested in in the first place.

I hope it helped,
Marcel

> 
> > @@ -4376,14 +4378,15 @@ int main(int argc, char **argv, char **envp)
> >      if (snapshot)
> >          qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
> >      if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func,
> > -                          &machine_class->block_default_type, 1) != 0) {
> > +                          machine_class, 1) != 0) {
> >          exit(1);
> >      }
> >  
> >      default_drive(default_cdrom, snapshot, machine_class->block_default_type, 2,
> > -                  CDROM_OPTS);
> > -    default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
> > -    default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
> > +                  CDROM_OPTS, machine_class);
> > +    default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS,
> > +                  machine_class);
> > +    default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS, machine_class);
> >  
> >      if (qemu_opts_foreach(qemu_find_opts("numa"), numa_init_func,
> >                            NULL, 1) != 0) {

  reply	other threads:[~2014-09-21  9:35 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-18 17:59 [Qemu-devel] [RFC v2 0/3] Q35/AHCI -cdrom/-hda desugaring John Snow
2014-09-18 17:59 ` [Qemu-devel] [RFC v2 1/3] blockdev: Add function to search for orphaned drives John Snow
2014-09-19  8:28   ` Markus Armbruster
2014-09-19 15:50     ` John Snow
2014-09-18 17:59 ` [Qemu-devel] [RFC v2 2/3] Add units-per-idebus property John Snow
2014-09-19  9:39   ` Markus Armbruster
2014-09-21  9:34     ` Marcel Apfelbaum [this message]
2014-09-22  7:51       ` Markus Armbruster
2014-09-18 17:59 ` [Qemu-devel] [RFC v2 3/3] ahci: implement -cdrom and -hd[a-d] John Snow
2014-09-19  9:49   ` Markus Armbruster
2014-09-19  9:53 ` [Qemu-devel] [RFC v2 0/3] Q35/AHCI -cdrom/-hda desugaring Markus Armbruster
2014-09-22 23:17   ` John Snow
2014-09-23  7:36     ` Markus Armbruster

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=1411292054.3666.78.camel@localhost.localdomain \
    --to=marcel.a@redhat.com \
    --cc=armbru@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=qemu-devel@nongnu.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).