[SeaBIOS] [PATCH 1/2] scsi: ensure LUN0 is added first

Paolo Bonzini pbonzini at redhat.com
Tue Jun 20 14:42:15 CEST 2017



On 19/06/2017 23:55, Roman Kagan wrote:
> On Mon, Jun 19, 2017 at 06:21:09PM +0200, Paolo Bonzini wrote:
>> The introduction of REPORT LUNS caused a potential regression when
>> many disks are present on the same SCSI target.  If LUN0 is processed
>> too late, SeaBIOS might run out of memory and fail to register it.
>>
>> There are two kinds of problems:
>>
>> - QEMU presents the results of REPORT LUNS in the opposite order
>>   to the "-device" command-line options.  It's likely that LUN 0
>>   will be first in the command-line, and thus will be processed
>>   last by SeaBIOS.
>>
>> - QEMU registers all LUNs in each target first.  It's thus possible
>>   that LUN 0 of target 1 is processed after many LUNs of target 0
>>   and not be able to allocate memory.
> 
> Am I correct that this is not two problems but one: the recently added
> REPORT LUNS enumeration made more disks visible to SeaBIOS, so that
> their control structures may not all fit in the limited available
> memory, and their unfortunate ordering may result in the most relevant
> drives falling out?

Yes, I listed them separately because you could fix the first by e.g.
sorting the REPORT LUNS output.

>> To fix both, the SCSI scans are modified to operate in two phases;
>> LUN 0 is scanned before the REPORT LUNS command is sent.  A possible
>> future enhancement is to remember the results of the scan in a
>> 32-byte bitmap, and skip the REPORT LUNS command during the second
>> phase.
>>
>> When multiple SCSI controllers are found, it's still possible to
>> have a regression because they are scanned in parallel.
> 
> I think there's a simpler but more reliable solution.  One can safely
> assume that the operating systems that use BIOS to access hard drives
> aren't interested in that many LUNs being visible.  So we can just skip
> calling scsi_drive_setup() and return non-zero from the respective
> add_lun functions if the lun number is above some predefined number
> (say, 2 or 8) and it doesn't appear on the fw_cfg bootorder list, e.g.

I'm not sure about the reliability; in practice this is a corner case
and there is room for many LUNs in the upper memory blocks, and ignoring
some LUNs (but not all of them) may produce unexpected results on some
configurations.

I also kind of liked the idea of reusing the result of the LUN0 scan to
speed up virtio-scsi boot. :)

Paolo

> 
> --- a/src/hw/virtio-scsi.c
> +++ b/src/hw/virtio-scsi.c
> @@ -114,6 +114,12 @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
>  {
>      struct virtio_lun_s *tmpl_vlun =
>          container_of(tmpl_drv, struct virtio_lun_s, drive);
> +    int prio = bootprio_find_scsi_device(tmpl_vlun->pci, tmpl_vlun->target,
> +                                        lun);
> +
> +    if (prio < 0 && lun >= SCSI_MAX_NONBOOT_LUNS)
> +        return -1;
> +
>      struct virtio_lun_s *vlun = malloc_fseg(sizeof(*vlun));
>      if (!vlun) {
>          warn_noalloc();
> @@ -122,7 +128,6 @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
>      virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq,
>                           tmpl_vlun->target, lun);
> 
> -    int prio = bootprio_find_scsi_device(vlun->pci, vlun->target, vlun->lun);
>      int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio);
>      if (ret)
>          goto fail;
> 
> Alternatively, one can pass the lun number to scsi_drive_setup and move
> this logic there.
> 
> This way we keep the possibilty to boot off any available lun, but will
> ignore higher luns otherwise for DOS and friends.
> 
> Would it work for your case?
> 
> Roman.
> 



More information about the SeaBIOS mailing list