Philippe Mathieu-Daudé <f4...@amsat.org> writes: > On 11/15/21 16:57, Markus Armbruster wrote: >> Philippe Mathieu-Daudé <f4...@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 <arm...@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 sloppiness. 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 -pflash. 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 optional. 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. Questions?