>-----Original Message-----
>From: Alex Williamson <alex.william...@redhat.com>
>Subject: Re: [PATCH v1 06/22] vfio/common: Add a vfio device iterator
>
>On Wed, 30 Aug 2023 18:37:38 +0800
>Zhenzhong Duan <zhenzhong.d...@intel.com> wrote:
>
>> With a vfio device iterator added, we can make some migration and reset
>> related functions group agnostic.
>> E.x:
>> vfio_mig_active
>> vfio_migratable_device_num
>> vfio_devices_all_dirty_tracking
>> vfio_devices_all_device_dirty_tracking
>> vfio_devices_all_running_and_mig_active
>> vfio_devices_dma_logging_stop
>> vfio_devices_dma_logging_start
>> vfio_devices_query_dirty_bitmap
>> vfio_reset_handler
>>
>> Or else we need to add container specific callback variants for above
>> functions just because they iterate devices based on group.
>>
>> Move the reset handler registration/unregistration to a place that is not
>> group specific, saying first vfio address space created instead of the
>> first group.
>>
>> Signed-off-by: Zhenzhong Duan <zhenzhong.d...@intel.com>
>> ---
>>  hw/vfio/common.c | 224 ++++++++++++++++++++++++++---------------------
>>  1 file changed, 122 insertions(+), 102 deletions(-)
>>
>> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
>> index 949ad6714a..51c6e7598e 100644
>> --- a/hw/vfio/common.c
>> +++ b/hw/vfio/common.c
>> @@ -84,6 +84,26 @@ static int vfio_ram_block_discard_disable(VFIOContainer
>*container, bool state)
>>      }
>>  }
>>
>> +static VFIODevice *vfio_container_dev_iter_next(VFIOContainer *container,
>> +                                                VFIODevice *curr)
>> +{
>> +    VFIOGroup *group;
>> +
>> +    if (!curr) {
>> +        group = QLIST_FIRST(&container->group_list);
>> +    } else {
>> +        if (curr->next.le_next) {
>> +            return curr->next.le_next;
>> +        }
>
>
>VFIODevice *device = QLIST_NEXT(curr, next);
>
>if (device) {
>    return device;
>}
>
>> +        group = curr->group->container_next.le_next;
>
>
>group = QLIST_NEXT(curr->group, container_next);
>
>> +    }
>> +
>> +    if (!group) {
>> +        return NULL;
>> +    }
>> +    return QLIST_FIRST(&group->device_list);
>> +}
>> +
>>  /*
>>   * Device state interfaces
>>   */
>> @@ -112,17 +132,22 @@ static int vfio_get_dirty_bitmap(VFIOContainer
>*container, uint64_t iova,
>>
>>  bool vfio_mig_active(void)
>>  {
>> -    VFIOGroup *group;
>> +    VFIOAddressSpace *space;
>> +    VFIOContainer *container;
>>      VFIODevice *vbasedev;
>>
>> -    if (QLIST_EMPTY(&vfio_group_list)) {
>> +    if (QLIST_EMPTY(&vfio_address_spaces)) {
>>          return false;
>>      }
>>
>> -    QLIST_FOREACH(group, &vfio_group_list, next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (vbasedev->migration_blocker) {
>> -                return false;
>> +    QLIST_FOREACH(space, &vfio_address_spaces, list) {
>> +        QLIST_FOREACH(container, &space->containers, next) {
>> +            vbasedev = NULL;
>> +            while ((vbasedev = vfio_container_dev_iter_next(container,
>> +                                                            vbasedev))) {
>> +                if (vbasedev->migration_blocker) {
>> +                    return false;
>> +                }
>
>Appears easy to avoid setting vbasedev in the loop iterator and
>improving the scope of vbasedev:
>
>VFIODevice *vbasedev = vfio_container_dev_iter_next(container, NULL);
>
>while (vbasedev) {
>    if (vbasedev->migration_blocker) {
>        return false;
>    }
>
>    vbasedev = vfio_container_dev_iter_next(container, vbasedev);
>}
>
>>              }
>>          }
>>      }
>> @@ -133,14 +158,19 @@ static Error *multiple_devices_migration_blocker;
>>
>>  static unsigned int vfio_migratable_device_num(void)
>>  {
>> -    VFIOGroup *group;
>> +    VFIOAddressSpace *space;
>> +    VFIOContainer *container;
>>      VFIODevice *vbasedev;
>>      unsigned int device_num = 0;
>>
>> -    QLIST_FOREACH(group, &vfio_group_list, next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (vbasedev->migration) {
>> -                device_num++;
>> +    QLIST_FOREACH(space, &vfio_address_spaces, list) {
>> +        QLIST_FOREACH(container, &space->containers, next) {
>> +            vbasedev = NULL;
>> +            while ((vbasedev = vfio_container_dev_iter_next(container,
>> +                                                            vbasedev))) {
>> +                if (vbasedev->migration) {
>> +                    device_num++;
>> +                }
>
>Same as above.
>
>>              }
>>          }
>>      }
>> @@ -207,8 +237,7 @@ static void vfio_set_migration_error(int err)
>>
>>  static bool vfio_devices_all_dirty_tracking(VFIOContainer *container)
>>  {
>> -    VFIOGroup *group;
>> -    VFIODevice *vbasedev;
>> +    VFIODevice *vbasedev = NULL;
>>      MigrationState *ms = migrate_get_current();
>>
>>      if (ms->state != MIGRATION_STATUS_ACTIVE &&
>> @@ -216,19 +245,17 @@ static bool
>vfio_devices_all_dirty_tracking(VFIOContainer *container)
>>          return false;
>>      }
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            VFIOMigration *migration = vbasedev->migration;
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        VFIOMigration *migration = vbasedev->migration;
>
>Similar, and all the other loops below.
>
>>
>> -            if (!migration) {
>> -                return false;
>> -            }
>> +        if (!migration) {
>> +            return false;
>> +        }
>>
>> -            if (vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF &&
>> -                (migration->device_state == VFIO_DEVICE_STATE_RUNNING ||
>> -                 migration->device_state == VFIO_DEVICE_STATE_PRE_COPY)) {
>> -                return false;
>> -            }
>> +        if (vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF &&
>> +            (migration->device_state == VFIO_DEVICE_STATE_RUNNING ||
>> +             migration->device_state == VFIO_DEVICE_STATE_PRE_COPY)) {
>> +            return false;
>>          }
>>      }
>>      return true;
>> @@ -236,14 +263,11 @@ static bool
>vfio_devices_all_dirty_tracking(VFIOContainer *container)
>>
>>  static bool vfio_devices_all_device_dirty_tracking(VFIOContainer *container)
>>  {
>> -    VFIOGroup *group;
>> -    VFIODevice *vbasedev;
>> +    VFIODevice *vbasedev = NULL;
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (!vbasedev->dirty_pages_supported) {
>> -                return false;
>> -            }
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        if (!vbasedev->dirty_pages_supported) {
>> +            return false;
>>          }
>>      }
>>
>> @@ -256,27 +280,24 @@ static bool
>vfio_devices_all_device_dirty_tracking(VFIOContainer *container)
>>   */
>>  static bool vfio_devices_all_running_and_mig_active(VFIOContainer
>*container)
>>  {
>> -    VFIOGroup *group;
>> -    VFIODevice *vbasedev;
>> +    VFIODevice *vbasedev = NULL;
>>
>>      if (!migration_is_active(migrate_get_current())) {
>>          return false;
>>      }
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            VFIOMigration *migration = vbasedev->migration;
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        VFIOMigration *migration = vbasedev->migration;
>>
>> -            if (!migration) {
>> -                return false;
>> -            }
>> +        if (!migration) {
>> +            return false;
>> +        }
>>
>> -            if (migration->device_state == VFIO_DEVICE_STATE_RUNNING ||
>> -                migration->device_state == VFIO_DEVICE_STATE_PRE_COPY) {
>> -                continue;
>> -            } else {
>> -                return false;
>> -            }
>> +        if (migration->device_state == VFIO_DEVICE_STATE_RUNNING ||
>> +            migration->device_state == VFIO_DEVICE_STATE_PRE_COPY) {
>> +            continue;
>> +        } else {
>> +            return false;
>>          }
>>      }
>>      return true;
>> @@ -1243,25 +1264,22 @@ static void
>vfio_devices_dma_logging_stop(VFIOContainer *container)
>>      uint64_t buf[DIV_ROUND_UP(sizeof(struct vfio_device_feature),
>>                                sizeof(uint64_t))] = {};
>>      struct vfio_device_feature *feature = (struct vfio_device_feature *)buf;
>> -    VFIODevice *vbasedev;
>> -    VFIOGroup *group;
>> +    VFIODevice *vbasedev = NULL;
>>
>>      feature->argsz = sizeof(buf);
>>      feature->flags = VFIO_DEVICE_FEATURE_SET |
>>                       VFIO_DEVICE_FEATURE_DMA_LOGGING_STOP;
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (!vbasedev->dirty_tracking) {
>> -                continue;
>> -            }
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        if (!vbasedev->dirty_tracking) {
>> +            continue;
>> +        }
>>
>> -            if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) {
>> -                warn_report("%s: Failed to stop DMA logging, err %d (%s)",
>> -                             vbasedev->name, -errno, strerror(errno));
>> -            }
>> -            vbasedev->dirty_tracking = false;
>> +        if (ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature)) {
>> +            warn_report("%s: Failed to stop DMA logging, err %d (%s)",
>> +                        vbasedev->name, -errno, strerror(errno));
>>          }
>> +        vbasedev->dirty_tracking = false;
>>      }
>>  }
>>
>> @@ -1336,8 +1354,7 @@ static int
>vfio_devices_dma_logging_start(VFIOContainer *container)
>>  {
>>      struct vfio_device_feature *feature;
>>      VFIODirtyRanges ranges;
>> -    VFIODevice *vbasedev;
>> -    VFIOGroup *group;
>> +    VFIODevice *vbasedev = NULL;
>>      int ret = 0;
>>
>>      vfio_dirty_tracking_init(container, &ranges);
>> @@ -1347,21 +1364,19 @@ static int
>vfio_devices_dma_logging_start(VFIOContainer *container)
>>          return -errno;
>>      }
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (vbasedev->dirty_tracking) {
>> -                continue;
>> -            }
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        if (vbasedev->dirty_tracking) {
>> +            continue;
>> +        }
>>
>> -            ret = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature);
>> -            if (ret) {
>> -                ret = -errno;
>> -                error_report("%s: Failed to start DMA logging, err %d (%s)",
>> -                             vbasedev->name, ret, strerror(errno));
>> -                goto out;
>> -            }
>> -            vbasedev->dirty_tracking = true;
>> +        ret = ioctl(vbasedev->fd, VFIO_DEVICE_FEATURE, feature);
>> +        if (ret) {
>> +            ret = -errno;
>> +            error_report("%s: Failed to start DMA logging, err %d (%s)",
>> +                         vbasedev->name, ret, strerror(errno));
>> +            goto out;
>>          }
>> +        vbasedev->dirty_tracking = true;
>>      }
>>
>>  out:
>> @@ -1440,22 +1455,19 @@ static int
>vfio_devices_query_dirty_bitmap(VFIOContainer *container,
>>                                             VFIOBitmap *vbmap, hwaddr iova,
>>                                             hwaddr size)
>>  {
>> -    VFIODevice *vbasedev;
>> -    VFIOGroup *group;
>> +    VFIODevice *vbasedev = NULL;
>>      int ret;
>>
>> -    QLIST_FOREACH(group, &container->group_list, container_next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            ret = vfio_device_dma_logging_report(vbasedev, iova, size,
>> -                                                 vbmap->bitmap);
>> -            if (ret) {
>> -                error_report("%s: Failed to get DMA logging report, iova: "
>> -                             "0x%" HWADDR_PRIx ", size: 0x%" HWADDR_PRIx
>> -                             ", err: %d (%s)",
>> -                             vbasedev->name, iova, size, ret, 
>> strerror(-ret));
>> +    while ((vbasedev = vfio_container_dev_iter_next(container, vbasedev))) {
>> +        ret = vfio_device_dma_logging_report(vbasedev, iova, size,
>> +                                             vbmap->bitmap);
>> +        if (ret) {
>> +            error_report("%s: Failed to get DMA logging report, iova: "
>> +                         "0x%" HWADDR_PRIx ", size: 0x%" HWADDR_PRIx
>> +                         ", err: %d (%s)",
>> +                         vbasedev->name, iova, size, ret, strerror(-ret));
>>
>> -                return ret;
>> -            }
>> +            return ret;
>>          }
>>      }
>>
>> @@ -1739,21 +1751,30 @@ bool vfio_get_info_dma_avail(struct
>vfio_iommu_type1_info *info,
>>
>>  void vfio_reset_handler(void *opaque)
>>  {
>> -    VFIOGroup *group;
>> +    VFIOAddressSpace *space;
>> +    VFIOContainer *container;
>>      VFIODevice *vbasedev;
>>
>> -    QLIST_FOREACH(group, &vfio_group_list, next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (vbasedev->dev->realized) {
>> -                vbasedev->ops->vfio_compute_needs_reset(vbasedev);
>> +    QLIST_FOREACH(space, &vfio_address_spaces, list) {
>> +        QLIST_FOREACH(container, &space->containers, next) {
>> +            vbasedev = NULL;
>> +            while ((vbasedev = vfio_container_dev_iter_next(container,
>> +                                                            vbasedev))) {
>> +                if (vbasedev->dev->realized) {
>> +                    vbasedev->ops->vfio_compute_needs_reset(vbasedev);
>> +                }
>>              }
>>          }
>>      }
>>
>> -    QLIST_FOREACH(group, &vfio_group_list, next) {
>> -        QLIST_FOREACH(vbasedev, &group->device_list, next) {
>> -            if (vbasedev->dev->realized && vbasedev->needs_reset) {
>> -                vbasedev->ops->vfio_hot_reset_multi(vbasedev);
>> +    QLIST_FOREACH(space, &vfio_address_spaces, list) {
>> +        QLIST_FOREACH(container, &space->containers, next) {
>> +            vbasedev = NULL;
>> +            while ((vbasedev = vfio_container_dev_iter_next(container,
>> +                                                            vbasedev))) {
>> +                if (vbasedev->dev->realized && vbasedev->needs_reset) {
>> +                    vbasedev->ops->vfio_hot_reset_multi(vbasedev);
>> +                    }
>>              }
>>          }
>>      }
>> @@ -1841,6 +1862,10 @@ static VFIOAddressSpace
>*vfio_get_address_space(AddressSpace *as)
>>      space->as = as;
>>      QLIST_INIT(&space->containers);
>>
>> +    if (QLIST_EMPTY(&vfio_address_spaces)) {
>> +        qemu_register_reset(vfio_reset_handler, NULL);
>> +    }
>> +
>
>We could just have a vfio_device_list to avoid iterating either
>containers and group or address spaces.  Thanks,

Good idea! Will do.
A vfio_device_list can be used by both BEs and I can have this
patch dropped.

Thanks
Zhenzhong

Reply via email to