John Snow <js...@redhat.com> writes: > The if_max_devs table as in the past been an immutable > default that controls the mapping of index => (bus,unit) > for all boards and all HBAs for each interface type. > > Since adding this mapping information to the HBA device > itself is currently unwieldly from the perspective of > retrieving this information at option parsing time > (e.g, within drive_new), we consider the alternative > of marking the if_max_devs table mutable so that > later configuration and initialization can adjust the > mapping at will, but only up until a drive is added, > at which point the mapping is finalized. > > Signed-off-by: John Snow <js...@redhat.com> > --- > blockdev.c | 26 +++++++++++++++++++++++++- > include/sysemu/blockdev.h | 2 ++ > 2 files changed, 27 insertions(+), 1 deletion(-) > > diff --git a/blockdev.c b/blockdev.c > index 81398e7..9b05f1b 100644 > --- a/blockdev.c > +++ b/blockdev.c > @@ -60,7 +60,7 @@ static const char *const if_name[IF_COUNT] = { > [IF_XEN] = "xen", > }; > > -static const int if_max_devs[IF_COUNT] = { > +static int if_max_devs[IF_COUNT] = { > /* > * Do not change these numbers! They govern how drive option > * index maps to unit and bus. That mapping is ABI. > @@ -79,6 +79,30 @@ static const int if_max_devs[IF_COUNT] = { > [IF_SCSI] = 7, > }; > > +/** > + * Boards may call this to offer board-by-board overrides > + * of the default, global values. > + */ > +void override_max_devs(BlockInterfaceType type, int max_devs) > +{ > + DriveInfo *dinfo; > + > + if (max_devs <= 0) { > + return; > + } > + > + QTAILQ_FOREACH(dinfo, &drives, next) { > + if (dinfo->type == type) { > + fprintf(stderr, "Cannot override units-per-bus property of" > + " the %s interface, because a drive of that type has" > + " already been added.\n", if_name[type]); > + g_assert_not_reached(); > + }
I'd prefer a straightforward QTAILQ_FOREACH(dinfo, &drives, next) { assert(dinfo->type != type); } or even assert(QTAILQ_EMPTY(drives)); assuming it actually holds. > + } > + > + if_max_devs[type] = max_devs; > +} > + > /* > * We automatically delete the drive when a device using it gets > * unplugged. Questionable feature, but we can't just drop it. > diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h > index 80f768d..f23d495 100644 > --- a/include/sysemu/blockdev.h > +++ b/include/sysemu/blockdev.h > @@ -46,6 +46,8 @@ struct DriveInfo { > QTAILQ_ENTRY(DriveInfo) next; > }; > > +void override_max_devs(BlockInterfaceType type, int max_devs); > + > DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); > bool drive_check_orphaned(void); > DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);