[Top][All Lists]

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

Re: [PATCH RFC 2/2] hw: Replace drive_get_next() by drive_get()

From: Markus Armbruster
Subject: Re: [PATCH RFC 2/2] hw: Replace drive_get_next() by drive_get()
Date: Tue, 16 Nov 2021 08:47:22 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)

Philippe Mathieu-Daudé <f4bug@amsat.org> writes:

> On 11/15/21 16:57, Markus Armbruster wrote:
>> Philippe Mathieu-Daudé <f4bug@amsat.org> writes:
>>> On 11/15/21 13:55, Markus Armbruster wrote:
>>>> drive_get_next() is basically a bad idea.  It returns the "next" block
>>>> backend of a certain interface type.  "Next" means bus=0,unit=N, where
>>>> subsequent calls count N up from zero, per interface type.
>>>> This lets you define unit numbers implicitly by execution order.  If the
>>>> order changes, or new calls appear "in the middle", unit numbers change.
>>>> ABI break.  Hard to spot in review.
>>>> Explicit is better than implicit: use drive_get() directly.
>>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>>> ---
>>>> @@ -435,11 +438,13 @@ static void aspeed_machine_init(MachineState 
>>>> *machine)
>>>>      }
>>>>      for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
>>>> -        sdhci_attach_drive(&bmc->soc.sdhci.slots[i], 
>>>> drive_get_next(IF_SD));
>>>> +        sdhci_attach_drive(&bmc->soc.sdhci.slots[i],
>>>> +                           drive_get(IF_SD, 0, i));
>>> If we put SD on bus #0, ...
>>>>      }
>>>>      if (bmc->soc.emmc.num_slots) {
>>>> -        sdhci_attach_drive(&bmc->soc.emmc.slots[0], 
>>>> drive_get_next(IF_SD));
>>>> +        sdhci_attach_drive(&bmc->soc.emmc.slots[0],
>>>> +                           drive_get(IF_SD, 0, bmc->soc.sdhci.num_slots));
>>> ... we'd want to put eMMC on bus #1
>> Using separate buses for different kinds of devices would be neater, but
>> it also would be an incompatible change.  This patch keeps existing
>> bus/unit numbers working.  drive_get_next() can only use bus 0.
>>>                                      but I see having eMMC cards on a
>>> IF_SD bus as a bug, since these cards are soldered on the board.
>> IF_SD is not a bus, it's an "block interface type", which is really just
>> a user interface thing.
> Why are we discriminating by "block interface type" then?
> What is the difference between "block interfaces"? I see a block drive
> as a generic unit, usable on multiple hardware devices.
> I never really understood how this "block interface type" helps
> developers and users. I thought BlockInterfaceType and DriveInfo
> were legacy / deprecated APIs we want to get rid of; and we would
> come up with a replacement API using BlockDeviceInfo or providing
> a BlockFrontend state of the art object.
> Anyway, I suppose the explanation is buried in the git history
> before the last 8 years. I need to keep reading.

In the beginning (v0.4.2), there was -hda and -hdb, and life was simple.

Then there was -hdc, -hdd, -cdrom (v0.5.1), -fda, -fdb (v0.6.0),
-mtdblock, -sd, -pflash (v0.9.1).

All these options do two things: they create a block backend, and they
request the board to create a certain block frontend for it, similar to
other options of this vintage, like -serial, -parallel, and -net.
Boards generally ignore requests they don't understand, but that's just

For each set of related options, there was a global variable holding the
requests: bs_table[] for -hda, -hdb, -hdc, -hdd, -cdrom; fd_table[]
-fda, -fdb; mtd_bdrv for -mtd; sd_drv for -ds; pflash_table[] for

The options replaced prior ones, except for -pflash, which appended to
its table.

bs_table[]'s index had a peculiar meaning: it's bus * MAX_IDE_DEVS +
unit.  This ensures that -hda (index 0) goes on IDE bus 0 as unit 0;
-hdb on bus 0, unit 1; -hdc on 1, 0; -hdc on 1, 1.

Life was now complicated enough for a generalization (v0.9.1), so there
was -drive (v0.9.1).  All the variables holding requests were fused into
drives_table[].  Table elements are identified by (type, bus, unit),
where type is an enum whose members correspond to the old global
variables: IF_IDE for bs_table[], IF_FLOPPY for fd_table[], and so
forth.  So:

    -hda becomes type = IF_IDE, bus = 0, unit = 0
    -hdb becomes type = IF_IDE, bus = 0, unit = 1
    -sd becomes type = IF_SD, bus = 0, unit = 0
    1st -pflash becomes type = IF_PFLASH, bus = 0, unit = 0
    2nd -pflash becomes type = IF_PFLASH, bus = 0, unit = 1

Other mappings from old to new global variables would have been
possible.  I figure this one was chosen because it comes with a
reasonable user interface.  Identifying block devices by (interface
type, bus, unit) is certainly nicer than by index in bs_table[].  Since
bus and/or unit make sense only with some interface types, they are

Things calmed down for a couple of years, until -device appeared
(v0.12).  Now we needed a way to define just a backend, without
requesting a frontend from the board.  Instead of inventing a new
option, this became IF_NONE, with meaningless bus and unit.

Over the next years, the block layer outgrew -drive's limited
capabilities to define frontends.  -blockdev appeard (v1.7.0) and
matured over several releases.  I don't remember exactly when it became
stable, relegating -drive if=none to legacy status.

What's *not* legacy is -drive with other interface types, simply because
there is no replacement.  Yet.  We clearly want one.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]