* [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows
@ 2019-01-14 9:03 mhines
2019-01-14 9:24 ` no-reply
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: mhines @ 2019-01-14 9:03 UTC (permalink / raw)
To: qemu-devel; +Cc: Matt Hines, Michael Roth
From: Matt Hines <mhines@scalecomputing.com>
Signed-off-by: Matt Hines <mhines@scalecomputing.com>
---
configure | 2 +-
qga/commands-win32.c | 295 +++++++++++++++++++++++++++++++++------------------
qga/qapi-schema.json | 3 +-
3 files changed, 197 insertions(+), 103 deletions(-)
diff --git a/configure b/configure
index 5b1d83ea26..46f21c089f 100755
--- a/configure
+++ b/configure
@@ -4694,7 +4694,7 @@ int main(void) {
EOF
if compile_prog "" "" ; then
guest_agent_ntddscsi=yes
- libs_qga="-lsetupapi $libs_qga"
+ libs_qga="-lsetupapi -lcfgmgr32 $libs_qga"
fi
fi
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 62e1b51dfe..8c8f3a2c65 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -26,6 +26,7 @@
#include <winioctl.h>
#include <ntddscsi.h>
#include <setupapi.h>
+#include <cfgmgr32.h>
#include <initguid.h>
#endif
#include <lm.h>
@@ -491,56 +492,29 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
return win2qemu[(int)bus];
}
-/* XXX: The following function is BROKEN!
- *
- * It does not work and probably has never worked. When we query for list of
- * disks we get cryptic names like "\Device\0000001d" instead of
- * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one
- * way or the other for comparison is an open question.
- *
- * When we query volume names (the original version) we are able to match those
- * but then the property queries report error "Invalid function". (duh!)
- */
-
-/*
-DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
- 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
- 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-*/
DEFINE_GUID(GUID_DEVINTERFACE_DISK,
0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
+DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
+ 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
+ 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-
-static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
+static GuestPCIAddress *get_pci_info(int number, Error **errp)
{
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_info_data;
- DWORD size = 0;
+ SP_DEVICE_INTERFACE_DATA dev_iface_data;
+ HANDLE dev_file;
int i;
- char dev_name[MAX_PATH];
- char *buffer = NULL;
GuestPCIAddress *pci = NULL;
- char *name = NULL;
bool partial_pci = false;
+
pci = g_malloc0(sizeof(*pci));
pci->domain = -1;
pci->slot = -1;
pci->function = -1;
pci->bus = -1;
- if (g_str_has_prefix(guid, "\\\\.\\") ||
- g_str_has_prefix(guid, "\\\\?\\")) {
- name = g_strdup(guid + 4);
- } else {
- name = g_strdup(guid);
- }
-
- if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
- error_setg_win32(errp, GetLastError(), "failed to get dos device name");
- goto out;
- }
-
dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dev_info == INVALID_HANDLE_VALUE) {
@@ -550,90 +524,208 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
g_debug("enumerating devices");
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
- DWORD addr, bus, slot, data, size2;
- int func, dev;
- while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
- &data, (PBYTE)buffer, size,
- &size2)) {
- size = MAX(size, size2);
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- g_free(buffer);
- /* Double the size to avoid problems on
- * W2k MBCS systems per KB 888609.
- * https://support.microsoft.com/en-us/kb/259695 */
- buffer = g_malloc(size * 2);
- } else {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL;
+ STORAGE_DEVICE_NUMBER sdn;
+ char *parent_dev_id = NULL;
+ HDEVINFO parent_dev_info;
+ SP_DEVINFO_DATA parent_dev_info_data;
+ DWORD j;
+ DWORD size = 0;
+
+ g_debug("getting device path");
+ if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data,
+ &GUID_DEVINTERFACE_DISK, 0,
+ &dev_iface_data)) {
+ while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data,
+ pdev_iface_detail_data,
+ size, &size,
+ &dev_info_data)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ pdev_iface_detail_data = g_malloc(size);
+ pdev_iface_detail_data->cbSize =
+ sizeof(*pdev_iface_detail_data);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
+ }
+ }
+
+ dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
+ NULL);
+ g_free(pdev_iface_detail_data);
+
+ if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
+ NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
+ CloseHandle(dev_file);
error_setg_win32(errp, GetLastError(),
- "failed to get device name");
+ "failed to get device slot number");
goto free_dev_info;
}
- }
- if (g_strcmp0(buffer, dev_name)) {
- continue;
+ CloseHandle(dev_file);
+ if (sdn.DeviceNumber != number) {
+ continue;
+ }
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
}
- g_debug("found device %s", dev_name);
- /* There is no need to allocate buffer in the next functions. The size
- * is known and ULONG according to
- * https://support.microsoft.com/en-us/kb/253232
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
- */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
- debug_error("failed to get bus");
- bus = -1;
- partial_pci = true;
+ g_debug("found device slot %d. Getting storage controller", number);
+ {
+ CONFIGRET cr;
+ DEVINST dev_inst, parent_dev_inst;
+ ULONG dev_id_size = 0;
+
+ size = 0;
+ while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data,
+ parent_dev_id, size, &size)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ parent_dev_id = g_malloc(size);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance ID");
+ goto out;
+ }
+ }
+
+ /*
+ * CM API used here as opposed to
+ * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...)
+ * which exports are only available in mingw-w64 6+
+ */
+ cr = CM_Locate_DevInst(&dev_inst, parent_dev_id, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Locate_DevInst failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance");
+ goto out;
+ }
+ cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Parent failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device instance");
+ goto out;
+ }
+
+ cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID_Size failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID length");
+ goto out;
+ }
+
+ ++dev_id_size;
+ if (dev_id_size > size) {
+ g_free(parent_dev_id);
+ parent_dev_id = g_malloc(dev_id_size);
+ }
+
+ cr = CM_Get_Device_ID(parent_dev_inst, parent_dev_id, dev_id_size,
+ 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID");
+ goto out;
+ }
}
- /* The function retrieves the device's address. This value will be
- * transformed into device function and number */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
- debug_error("failed to get address");
- addr = -1;
- partial_pci = true;
+ g_debug("querying storage controller %s for PCI information",
+ parent_dev_id);
+ parent_dev_info =
+ SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id,
+ NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ g_free(parent_dev_id);
+
+ if (parent_dev_info == INVALID_HANDLE_VALUE) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device");
+ goto out;
}
- /* This call returns UINumber of DEVICE_CAPABILITIES structure.
- * This number is typically a user-perceived slot number. */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
- debug_error("failed to get slot");
- slot = -1;
- partial_pci = true;
+ parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device data");
+ goto out;
}
- /* SetupApi gives us the same information as driver with
- * IoGetDeviceProperty. According to Microsoft
- * https://support.microsoft.com/en-us/kb/253232
- * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
- * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
- * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
-
- if (partial_pci) {
- pci->domain = -1;
- pci->slot = -1;
- pci->function = -1;
- pci->bus = -1;
- } else {
- func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF;
- dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
- pci->domain = dev;
- pci->slot = (int) slot;
- pci->function = func;
- pci->bus = (int) bus;
+ for (j = 0;
+ SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
+ j++) {
+ DWORD addr, bus, slot, type;
+ int func, dev;
+
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
+ * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
+ */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
+ &type, (PBYTE)&bus, size, NULL)) {
+ debug_error("failed to get PCI bus");
+ bus = -1;
+ partial_pci = true;
+ }
+
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
+ &type, (PBYTE)&addr, size, NULL)) {
+ debug_error("failed to get PCI address");
+ addr = -1;
+ partial_pci = true;
+ }
+
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
+ &type, (PBYTE)&slot, size, NULL)) {
+ debug_error("failed to get PCI slot");
+ slot = -1;
+ partial_pci = true;
+ }
+
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
+ * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
+ * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
+ * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
+
+ if (partial_pci) {
+ pci->domain = -1;
+ pci->slot = -1;
+ pci->function = -1;
+ pci->bus = -1;
+ continue;
+ } else {
+ func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
+ dev = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
+ pci->domain = dev;
+ pci->slot = (int)slot;
+ pci->function = func;
+ pci->bus = (int)bus;
+ break;
+ }
}
+ SetupDiDestroyDeviceInfoList(parent_dev_info);
break;
}
free_dev_info:
SetupDiDestroyDeviceInfoList(dev_info);
out:
- g_free(buffer);
- g_free(name);
return pci;
}
@@ -720,7 +812,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
* if that doesn't hold since that suggests some other unexpected
* breakage
*/
- disk->pci_controller = get_pci_info(disk->dev, &local_err);
+ disk->pci_controller = get_pci_info(disk->number, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto err_close;
@@ -736,7 +828,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
/* We are able to use the same ioctls for different bus types
* according to Microsoft docs
* https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */
- g_debug("getting pci-controller info");
+ g_debug("getting SCSI info");
if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
sizeof(SCSI_ADDRESS), &len, NULL)) {
disk->unit = addr.Lun;
@@ -838,8 +930,9 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
* https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#win32-device-namespaces
*/
disk->has_dev = true;
+ disk->number = extents->Extents[i].DiskNumber;
disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
- extents->Extents[i].DiskNumber);
+ extents->Extents[i].DiskNumber);
get_single_disk_info(disk, &local_err);
if (local_err) {
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index c6725b3ec8..0a78fb2e3a 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -836,6 +836,7 @@
# @unit: unit id
# @serial: serial number (since: 3.1)
# @dev: device node (POSIX) or device UNC (Windows) (since: 3.1)
+# @number: device slot index (Windows)
#
# Since: 2.2
##
@@ -843,7 +844,7 @@
'data': {'pci-controller': 'GuestPCIAddress',
'bus-type': 'GuestDiskBusType',
'bus': 'int', 'target': 'int', 'unit': 'int',
- '*serial': 'str', '*dev': 'str'} }
+ '*serial': 'str', '*dev': 'str', 'number':'int'} }
##
# @GuestFilesystemInfo:
--
2.11.0.windows.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
@ 2019-01-14 9:24 ` no-reply
2019-01-14 19:41 ` Eric Blake
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: no-reply @ 2019-01-14 9:24 UTC (permalink / raw)
To: mhines; +Cc: fam, qemu-devel, mdroth
Patchew URL: https://patchew.org/QEMU/20190114090324.16176-1-mhines@scalecomputing.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Message-id: 20190114090324.16176-1-mhines@scalecomputing.com
Subject: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows
Type: series
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
58d8d80 QGA: Fix guest-get-fsinfo PCI address collection in Windows
=== OUTPUT BEGIN ===
WARNING: Block comments should align the * on each line
#189: FILE: qga/commands-win32.c:592:
+ /*
+ * CM API used here as opposed to
WARNING: line over 80 characters
#293: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments use a leading /* on a separate line
#293: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments should align the * on each line
#294: FILE: qga/commands-win32.c:662:
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
ERROR: spaces required around that '&' (ctx:VxV)
#299: FILE: qga/commands-win32.c:667:
+ &type, (PBYTE)&bus, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#317: FILE: qga/commands-win32.c:673:
+ /* The function retrieves the device's address. This value will be
WARNING: Block comments use a trailing */ on a separate line
#318: FILE: qga/commands-win32.c:674:
+ * transformed into device function and number */
WARNING: Block comments should align the * on each line
#318: FILE: qga/commands-win32.c:674:
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
ERROR: spaces required around that '&' (ctx:VxV)
#321: FILE: qga/commands-win32.c:677:
+ &type, (PBYTE)&addr, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#327: FILE: qga/commands-win32.c:683:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
WARNING: Block comments use a trailing */ on a separate line
#328: FILE: qga/commands-win32.c:684:
+ * This number is typically a user-perceived slot number. */
WARNING: Block comments should align the * on each line
#328: FILE: qga/commands-win32.c:684:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
ERROR: spaces required around that '&' (ctx:VxV)
#331: FILE: qga/commands-win32.c:687:
+ &type, (PBYTE)&slot, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#337: FILE: qga/commands-win32.c:693:
+ /* SetupApi gives us the same information as driver with
WARNING: Block comments should align the * on each line
#338: FILE: qga/commands-win32.c:694:
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
WARNING: Block comments use a trailing */ on a separate line
#342: FILE: qga/commands-win32.c:698:
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
total: 3 errors, 13 warnings, 391 lines checked
Commit 58d8d800f31a (QGA: Fix guest-get-fsinfo PCI address collection in Windows) has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20190114090324.16176-1-mhines@scalecomputing.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
2019-01-14 9:24 ` no-reply
@ 2019-01-14 19:41 ` Eric Blake
2019-01-14 20:37 ` [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI addresscollection " Matt Hines
2019-01-15 16:57 ` [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection " mhines
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Eric Blake @ 2019-01-14 19:41 UTC (permalink / raw)
To: mhines, qemu-devel; +Cc: Michael Roth
[-- Attachment #1: Type: text/plain, Size: 1301 bytes --]
On 1/14/19 3:03 AM, mhines@scalecomputing.com wrote:
> From: Matt Hines <mhines@scalecomputing.com>
>
> Signed-off-by: Matt Hines <mhines@scalecomputing.com>
The title says what (a fix), but no description of that fix or a "why"
in the commit body.
> ---
> configure | 2 +-
> qga/commands-win32.c | 295 +++++++++++++++++++++++++++++++++------------------
> qga/qapi-schema.json | 3 +-
> 3 files changed, 197 insertions(+), 103 deletions(-)
> +++ b/qga/qapi-schema.json
> @@ -836,6 +836,7 @@
> # @unit: unit id
> # @serial: serial number (since: 3.1)
> # @dev: device node (POSIX) or device UNC (Windows) (since: 3.1)
> +# @number: device slot index (Windows)
Adding a member is more than just a fix. Also, this is missing a
'(since 4.0)' tag.
> #
> # Since: 2.2
> ##
> @@ -843,7 +844,7 @@
> 'data': {'pci-controller': 'GuestPCIAddress',
> 'bus-type': 'GuestDiskBusType',
> 'bus': 'int', 'target': 'int', 'unit': 'int',
> - '*serial': 'str', '*dev': 'str'} }
> + '*serial': 'str', '*dev': 'str', 'number':'int'} }
>
> ##
> # @GuestFilesystemInfo:
>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI addresscollection in Windows
2019-01-14 19:41 ` Eric Blake
@ 2019-01-14 20:37 ` Matt Hines
0 siblings, 0 replies; 12+ messages in thread
From: Matt Hines @ 2019-01-14 20:37 UTC (permalink / raw)
To: Eric Blake, qemu-devel; +Cc: Michael Roth
Number here is specific to the device type (and otherwise opaque) unfortunately per this IOCtl: https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/ni-winioctl-ioctl_storage_get_device_number
Should I put a comment in qapi-schema.json pointing to this?
From: Eric Blake
Sent: Monday, January 14, 2019 11:41
To: mhines@scalecomputing.com; qemu-devel@nongnu.org
Cc: Michael Roth
Subject: Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI addresscollection in Windows
On 1/14/19 3:03 AM, mhines@scalecomputing.com wrote:
> From: Matt Hines <mhines@scalecomputing.com>
>
> Signed-off-by: Matt Hines <mhines@scalecomputing.com>
The title says what (a fix), but no description of that fix or a "why"
in the commit body.
> ---
> configure | 2 +-
> qga/commands-win32.c | 295 +++++++++++++++++++++++++++++++++------------------
> qga/qapi-schema.json | 3 +-
> 3 files changed, 197 insertions(+), 103 deletions(-)
> +++ b/qga/qapi-schema.json
> @@ -836,6 +836,7 @@
> # @unit: unit id
> # @serial: serial number (since: 3.1)
> # @dev: device node (POSIX) or device UNC (Windows) (since: 3.1)
> +# @number: device slot index (Windows)
Adding a member is more than just a fix. Also, this is missing a
'(since 4.0)' tag.
> #
> # Since: 2.2
> ##
> @@ -843,7 +844,7 @@
> 'data': {'pci-controller': 'GuestPCIAddress',
> 'bus-type': 'GuestDiskBusType',
> 'bus': 'int', 'target': 'int', 'unit': 'int',
> - '*serial': 'str', '*dev': 'str'} }
> + '*serial': 'str', '*dev': 'str', 'number':'int'} }
>
> ##
> # @GuestFilesystemInfo:
>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
2019-01-14 9:24 ` no-reply
2019-01-14 19:41 ` Eric Blake
@ 2019-01-15 16:57 ` mhines
2019-01-21 4:31 ` no-reply
2019-01-21 4:42 ` no-reply
2019-01-24 17:56 ` [Qemu-devel] [PATCH] " Michael Roth
2019-01-28 22:30 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
4 siblings, 2 replies; 12+ messages in thread
From: mhines @ 2019-01-15 16:57 UTC (permalink / raw)
To: qemu-devel; +Cc: eblake, Matt Hines, Michael Roth
From: Matt Hines <mhines@scalecomputing.com>
The Windows QEMU guest agent erroneously tries to collect PCI information
directly from the physical drive. However, windows stores SCSI/IDE information
with the drive and PCI information with the underlying storage controller
This changes get_pci_info to use the physical drive's underlying storage
controller to get PCI information.
Signed-off-by: Matt Hines <mhines@scalecomputing.com>
---
configure | 2 +-
qga/commands-win32.c | 301 +++++++++++++++++++++++++++++++++------------------
2 files changed, 198 insertions(+), 105 deletions(-)
diff --git a/configure b/configure
index 5b1d83ea26..46f21c089f 100755
--- a/configure
+++ b/configure
@@ -4694,7 +4694,7 @@ int main(void) {
EOF
if compile_prog "" "" ; then
guest_agent_ntddscsi=yes
- libs_qga="-lsetupapi $libs_qga"
+ libs_qga="-lsetupapi -lcfgmgr32 $libs_qga"
fi
fi
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 62e1b51dfe..200dfbe428 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -26,6 +26,7 @@
#include <winioctl.h>
#include <ntddscsi.h>
#include <setupapi.h>
+#include <cfgmgr32.h>
#include <initguid.h>
#endif
#include <lm.h>
@@ -491,56 +492,29 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
return win2qemu[(int)bus];
}
-/* XXX: The following function is BROKEN!
- *
- * It does not work and probably has never worked. When we query for list of
- * disks we get cryptic names like "\Device\0000001d" instead of
- * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one
- * way or the other for comparison is an open question.
- *
- * When we query volume names (the original version) we are able to match those
- * but then the property queries report error "Invalid function". (duh!)
- */
-
-/*
-DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
- 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
- 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-*/
DEFINE_GUID(GUID_DEVINTERFACE_DISK,
0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
+DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
+ 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
+ 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-
-static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
+static GuestPCIAddress *get_pci_info(int number, Error **errp)
{
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_info_data;
- DWORD size = 0;
+ SP_DEVICE_INTERFACE_DATA dev_iface_data;
+ HANDLE dev_file;
int i;
- char dev_name[MAX_PATH];
- char *buffer = NULL;
GuestPCIAddress *pci = NULL;
- char *name = NULL;
bool partial_pci = false;
+
pci = g_malloc0(sizeof(*pci));
pci->domain = -1;
pci->slot = -1;
pci->function = -1;
pci->bus = -1;
- if (g_str_has_prefix(guid, "\\\\.\\") ||
- g_str_has_prefix(guid, "\\\\?\\")) {
- name = g_strdup(guid + 4);
- } else {
- name = g_strdup(guid);
- }
-
- if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
- error_setg_win32(errp, GetLastError(), "failed to get dos device name");
- goto out;
- }
-
dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dev_info == INVALID_HANDLE_VALUE) {
@@ -550,90 +524,208 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
g_debug("enumerating devices");
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
- DWORD addr, bus, slot, data, size2;
- int func, dev;
- while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
- &data, (PBYTE)buffer, size,
- &size2)) {
- size = MAX(size, size2);
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- g_free(buffer);
- /* Double the size to avoid problems on
- * W2k MBCS systems per KB 888609.
- * https://support.microsoft.com/en-us/kb/259695 */
- buffer = g_malloc(size * 2);
- } else {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL;
+ STORAGE_DEVICE_NUMBER sdn;
+ char *parent_dev_id = NULL;
+ HDEVINFO parent_dev_info;
+ SP_DEVINFO_DATA parent_dev_info_data;
+ DWORD j;
+ DWORD size = 0;
+
+ g_debug("getting device path");
+ if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data,
+ &GUID_DEVINTERFACE_DISK, 0,
+ &dev_iface_data)) {
+ while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data,
+ pdev_iface_detail_data,
+ size, &size,
+ &dev_info_data)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ pdev_iface_detail_data = g_malloc(size);
+ pdev_iface_detail_data->cbSize =
+ sizeof(*pdev_iface_detail_data);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
+ }
+ }
+
+ dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
+ NULL);
+ g_free(pdev_iface_detail_data);
+
+ if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
+ NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
+ CloseHandle(dev_file);
error_setg_win32(errp, GetLastError(),
- "failed to get device name");
+ "failed to get device slot number");
goto free_dev_info;
}
- }
- if (g_strcmp0(buffer, dev_name)) {
- continue;
+ CloseHandle(dev_file);
+ if (sdn.DeviceNumber != number) {
+ continue;
+ }
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
}
- g_debug("found device %s", dev_name);
- /* There is no need to allocate buffer in the next functions. The size
- * is known and ULONG according to
- * https://support.microsoft.com/en-us/kb/253232
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
- */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
- debug_error("failed to get bus");
- bus = -1;
- partial_pci = true;
+ g_debug("found device slot %d. Getting storage controller", number);
+ {
+ CONFIGRET cr;
+ DEVINST dev_inst, parent_dev_inst;
+ ULONG dev_id_size = 0;
+
+ size = 0;
+ while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data,
+ parent_dev_id, size, &size)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ parent_dev_id = g_malloc(size);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance ID");
+ goto out;
+ }
+ }
+
+ /*
+ * CM API used here as opposed to
+ * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...)
+ * which exports are only available in mingw-w64 6+
+ */
+ cr = CM_Locate_DevInst(&dev_inst, parent_dev_id, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Locate_DevInst failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance");
+ goto out;
+ }
+ cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Parent failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device instance");
+ goto out;
+ }
+
+ cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID_Size failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID length");
+ goto out;
+ }
+
+ ++dev_id_size;
+ if (dev_id_size > size) {
+ g_free(parent_dev_id);
+ parent_dev_id = g_malloc(dev_id_size);
+ }
+
+ cr = CM_Get_Device_ID(parent_dev_inst, parent_dev_id, dev_id_size,
+ 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID");
+ goto out;
+ }
}
- /* The function retrieves the device's address. This value will be
- * transformed into device function and number */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
- debug_error("failed to get address");
- addr = -1;
- partial_pci = true;
+ g_debug("querying storage controller %s for PCI information",
+ parent_dev_id);
+ parent_dev_info =
+ SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id,
+ NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ g_free(parent_dev_id);
+
+ if (parent_dev_info == INVALID_HANDLE_VALUE) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device");
+ goto out;
}
- /* This call returns UINumber of DEVICE_CAPABILITIES structure.
- * This number is typically a user-perceived slot number. */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
- debug_error("failed to get slot");
- slot = -1;
- partial_pci = true;
+ parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device data");
+ goto out;
}
- /* SetupApi gives us the same information as driver with
- * IoGetDeviceProperty. According to Microsoft
- * https://support.microsoft.com/en-us/kb/253232
- * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
- * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
- * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
-
- if (partial_pci) {
- pci->domain = -1;
- pci->slot = -1;
- pci->function = -1;
- pci->bus = -1;
- } else {
- func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF;
- dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
- pci->domain = dev;
- pci->slot = (int) slot;
- pci->function = func;
- pci->bus = (int) bus;
+ for (j = 0;
+ SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
+ j++) {
+ DWORD addr, bus, slot, type;
+ int func, dev;
+
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
+ * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
+ */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
+ &type, (PBYTE)&bus, size, NULL)) {
+ debug_error("failed to get PCI bus");
+ bus = -1;
+ partial_pci = true;
+ }
+
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
+ &type, (PBYTE)&addr, size, NULL)) {
+ debug_error("failed to get PCI address");
+ addr = -1;
+ partial_pci = true;
+ }
+
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
+ &type, (PBYTE)&slot, size, NULL)) {
+ debug_error("failed to get PCI slot");
+ slot = -1;
+ partial_pci = true;
+ }
+
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
+ * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
+ * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
+ * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
+
+ if (partial_pci) {
+ pci->domain = -1;
+ pci->slot = -1;
+ pci->function = -1;
+ pci->bus = -1;
+ continue;
+ } else {
+ func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
+ dev = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
+ pci->domain = dev;
+ pci->slot = (int)slot;
+ pci->function = func;
+ pci->bus = (int)bus;
+ break;
+ }
}
+ SetupDiDestroyDeviceInfoList(parent_dev_info);
break;
}
free_dev_info:
SetupDiDestroyDeviceInfoList(dev_info);
out:
- g_free(buffer);
- g_free(name);
return pci;
}
@@ -691,7 +783,8 @@ out_free:
return;
}
-static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
+static void get_single_disk_info(int disk_number,
+ GuestDiskAddress *disk, Error **errp)
{
SCSI_ADDRESS addr, *scsi_ad;
DWORD len;
@@ -720,7 +813,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
* if that doesn't hold since that suggests some other unexpected
* breakage
*/
- disk->pci_controller = get_pci_info(disk->dev, &local_err);
+ disk->pci_controller = get_pci_info(disk_number, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto err_close;
@@ -736,7 +829,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
/* We are able to use the same ioctls for different bus types
* according to Microsoft docs
* https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */
- g_debug("getting pci-controller info");
+ g_debug("getting SCSI info");
if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
sizeof(SCSI_ADDRESS), &len, NULL)) {
disk->unit = addr.Lun;
@@ -805,7 +898,7 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
disk = g_malloc0(sizeof(GuestDiskAddress));
disk->has_dev = true;
disk->dev = g_strdup(name);
- get_single_disk_info(disk, &local_err);
+ get_single_disk_info(0xffffffff, disk, &local_err);
if (local_err) {
g_debug("failed to get disk info, ignoring error: %s",
error_get_pretty(local_err));
@@ -839,9 +932,9 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
*/
disk->has_dev = true;
disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
- extents->Extents[i].DiskNumber);
+ extents->Extents[i].DiskNumber);
- get_single_disk_info(disk, &local_err);
+ get_single_disk_info(extents->Extents[i].DiskNumber, disk, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto out;
--
2.11.0.windows.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-15 16:57 ` [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection " mhines
@ 2019-01-21 4:31 ` no-reply
2019-01-21 4:42 ` no-reply
1 sibling, 0 replies; 12+ messages in thread
From: no-reply @ 2019-01-21 4:31 UTC (permalink / raw)
To: mhines; +Cc: fam, qemu-devel, mdroth
Patchew URL: https://patchew.org/QEMU/20190115165710.20116-1-mhines@scalecomputing.com/
Hi,
This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.
=== TEST SCRIPT BEGIN ===
#!/bin/bash
time make docker-test-mingw@fedora SHOW_ENV=1 J=14
=== TEST SCRIPT END ===
CC hw/acpi/vmgenid.o
CC hw/acpi/acpi_interface.o
/tmp/qemu-test/src/block/sheepdog.c: In function 'find_vdi_name':
/tmp/qemu-test/src/block/sheepdog.c:1239:5: error: 'strncpy' specified bound 256 equals destination size [-Werror=stringop-truncation]
strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
---
make: *** Waiting for unfinished jobs....
In function 'acpi_table_install',
inlined from 'acpi_table_add' at /tmp/qemu-test/src/hw/acpi/core.c:296:5:
/tmp/qemu-test/src/hw/acpi/core.c:184:9: error: 'strncpy' specified bound 4 equals destination size [-Werror=stringop-truncation]
strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/qemu-test/src/hw/acpi/core.c:203:9: error: 'strncpy' specified bound 6 equals destination size [-Werror=stringop-truncation]
strncpy(ext_hdr->oem_id, hdrs->oem_id, sizeof ext_hdr->oem_id);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/qemu-test/src/hw/acpi/core.c:207:9: error: 'strncpy' specified bound 8 equals destination size [-Werror=stringop-truncation]
strncpy(ext_hdr->oem_table_id, hdrs->oem_table_id,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sizeof ext_hdr->oem_table_id);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/qemu-test/src/hw/acpi/core.c:216:9: error: 'strncpy' specified bound 4 equals destination size [-Werror=stringop-truncation]
strncpy(ext_hdr->asl_compiler_id, hdrs->asl_compiler_id,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sizeof ext_hdr->asl_compiler_id);
The full log is available at
http://patchew.org/logs/20190115165710.20116-1-mhines@scalecomputing.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-15 16:57 ` [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection " mhines
2019-01-21 4:31 ` no-reply
@ 2019-01-21 4:42 ` no-reply
1 sibling, 0 replies; 12+ messages in thread
From: no-reply @ 2019-01-21 4:42 UTC (permalink / raw)
To: mhines; +Cc: fam, qemu-devel, mdroth
Patchew URL: https://patchew.org/QEMU/20190115165710.20116-1-mhines@scalecomputing.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Message-id: 20190115165710.20116-1-mhines@scalecomputing.com
Type: series
Subject: [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection in Windows
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
85a7940 QGA: Fix guest-get-fsinfo PCI address collection in Windows
=== OUTPUT BEGIN ===
WARNING: Block comments should align the * on each line
#195: FILE: qga/commands-win32.c:592:
+ /*
+ * CM API used here as opposed to
WARNING: line over 80 characters
#299: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments use a leading /* on a separate line
#299: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments should align the * on each line
#300: FILE: qga/commands-win32.c:662:
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
ERROR: spaces required around that '&' (ctx:VxV)
#305: FILE: qga/commands-win32.c:667:
+ &type, (PBYTE)&bus, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#323: FILE: qga/commands-win32.c:673:
+ /* The function retrieves the device's address. This value will be
WARNING: Block comments use a trailing */ on a separate line
#324: FILE: qga/commands-win32.c:674:
+ * transformed into device function and number */
WARNING: Block comments should align the * on each line
#324: FILE: qga/commands-win32.c:674:
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
ERROR: spaces required around that '&' (ctx:VxV)
#327: FILE: qga/commands-win32.c:677:
+ &type, (PBYTE)&addr, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#333: FILE: qga/commands-win32.c:683:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
WARNING: Block comments use a trailing */ on a separate line
#334: FILE: qga/commands-win32.c:684:
+ * This number is typically a user-perceived slot number. */
WARNING: Block comments should align the * on each line
#334: FILE: qga/commands-win32.c:684:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
ERROR: spaces required around that '&' (ctx:VxV)
#337: FILE: qga/commands-win32.c:687:
+ &type, (PBYTE)&slot, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#343: FILE: qga/commands-win32.c:693:
+ /* SetupApi gives us the same information as driver with
WARNING: Block comments should align the * on each line
#344: FILE: qga/commands-win32.c:694:
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
WARNING: Block comments use a trailing */ on a separate line
#348: FILE: qga/commands-win32.c:698:
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
total: 3 errors, 13 warnings, 394 lines checked
Commit 85a794036de8 (QGA: Fix guest-get-fsinfo PCI address collection in Windows) has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20190115165710.20116-1-mhines@scalecomputing.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
` (2 preceding siblings ...)
2019-01-15 16:57 ` [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection " mhines
@ 2019-01-24 17:56 ` Michael Roth
2019-01-24 17:59 ` [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection inWindows Matt Hines
2019-01-28 22:30 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
4 siblings, 1 reply; 12+ messages in thread
From: Michael Roth @ 2019-01-24 17:56 UTC (permalink / raw)
To: mhines, qemu-devel
Quoting mhines@scalecomputing.com (2019-01-14 03:03:23)
> From: Matt Hines <mhines@scalecomputing.com>
>
> Signed-off-by: Matt Hines <mhines@scalecomputing.com>
> ---
> configure | 2 +-
> qga/commands-win32.c | 295 +++++++++++++++++++++++++++++++++------------------
> qga/qapi-schema.json | 3 +-
> 3 files changed, 197 insertions(+), 103 deletions(-)
>
> diff --git a/configure b/configure
> index 5b1d83ea26..46f21c089f 100755
> --- a/configure
> +++ b/configure
> @@ -4694,7 +4694,7 @@ int main(void) {
> EOF
> if compile_prog "" "" ; then
> guest_agent_ntddscsi=yes
> - libs_qga="-lsetupapi $libs_qga"
> + libs_qga="-lsetupapi -lcfgmgr32 $libs_qga"
> fi
> fi
>
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index 62e1b51dfe..8c8f3a2c65 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -26,6 +26,7 @@
> #include <winioctl.h>
> #include <ntddscsi.h>
> #include <setupapi.h>
> +#include <cfgmgr32.h>
> #include <initguid.h>
> #endif
> #include <lm.h>
> @@ -491,56 +492,29 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
> return win2qemu[(int)bus];
> }
>
> -/* XXX: The following function is BROKEN!
> - *
> - * It does not work and probably has never worked. When we query for list of
> - * disks we get cryptic names like "\Device\0000001d" instead of
> - * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one
> - * way or the other for comparison is an open question.
> - *
> - * When we query volume names (the original version) we are able to match those
> - * but then the property queries report error "Invalid function". (duh!)
> - */
> -
> -/*
> -DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
> - 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
> - 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
> -*/
> DEFINE_GUID(GUID_DEVINTERFACE_DISK,
> 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
> 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
> +DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
> + 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
> + 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
>
> -
> -static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
> +static GuestPCIAddress *get_pci_info(int number, Error **errp)
> {
> HDEVINFO dev_info;
> SP_DEVINFO_DATA dev_info_data;
> - DWORD size = 0;
> + SP_DEVICE_INTERFACE_DATA dev_iface_data;
> + HANDLE dev_file;
> int i;
> - char dev_name[MAX_PATH];
> - char *buffer = NULL;
> GuestPCIAddress *pci = NULL;
> - char *name = NULL;
> bool partial_pci = false;
> +
> pci = g_malloc0(sizeof(*pci));
> pci->domain = -1;
> pci->slot = -1;
> pci->function = -1;
> pci->bus = -1;
>
> - if (g_str_has_prefix(guid, "\\\\.\\") ||
> - g_str_has_prefix(guid, "\\\\?\\")) {
> - name = g_strdup(guid + 4);
> - } else {
> - name = g_strdup(guid);
> - }
> -
> - if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
> - error_setg_win32(errp, GetLastError(), "failed to get dos device name");
> - goto out;
> - }
> -
> dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
> DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
> if (dev_info == INVALID_HANDLE_VALUE) {
> @@ -550,90 +524,208 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
>
> g_debug("enumerating devices");
> dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
> + dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
> for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
> - DWORD addr, bus, slot, data, size2;
> - int func, dev;
> - while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
> - &data, (PBYTE)buffer, size,
> - &size2)) {
> - size = MAX(size, size2);
> - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> - g_free(buffer);
> - /* Double the size to avoid problems on
> - * W2k MBCS systems per KB 888609.
> - * https://support.microsoft.com/en-us/kb/259695 */
> - buffer = g_malloc(size * 2);
> - } else {
> + PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL;
> + STORAGE_DEVICE_NUMBER sdn;
> + char *parent_dev_id = NULL;
> + HDEVINFO parent_dev_info;
> + SP_DEVINFO_DATA parent_dev_info_data;
> + DWORD j;
> + DWORD size = 0;
> +
> + g_debug("getting device path");
> + if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data,
> + &GUID_DEVINTERFACE_DISK, 0,
> + &dev_iface_data)) {
> + while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data,
> + pdev_iface_detail_data,
> + size, &size,
> + &dev_info_data)) {
> + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> + pdev_iface_detail_data = g_malloc(size);
> + pdev_iface_detail_data->cbSize =
> + sizeof(*pdev_iface_detail_data);
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device interfaces");
> + goto free_dev_info;
> + }
> + }
> +
> + dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
> + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
> + NULL);
> + g_free(pdev_iface_detail_data);
> +
> + if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
> + NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
> + CloseHandle(dev_file);
> error_setg_win32(errp, GetLastError(),
> - "failed to get device name");
> + "failed to get device slot number");
> goto free_dev_info;
> }
> - }
>
> - if (g_strcmp0(buffer, dev_name)) {
> - continue;
> + CloseHandle(dev_file);
> + if (sdn.DeviceNumber != number) {
> + continue;
> + }
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device interfaces");
> + goto free_dev_info;
> }
> - g_debug("found device %s", dev_name);
>
> - /* There is no need to allocate buffer in the next functions. The size
> - * is known and ULONG according to
> - * https://support.microsoft.com/en-us/kb/253232
> - * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
> - */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
> - debug_error("failed to get bus");
> - bus = -1;
> - partial_pci = true;
> + g_debug("found device slot %d. Getting storage controller", number);
> + {
> + CONFIGRET cr;
> + DEVINST dev_inst, parent_dev_inst;
> + ULONG dev_id_size = 0;
> +
> + size = 0;
> + while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data,
> + parent_dev_id, size, &size)) {
> + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> + parent_dev_id = g_malloc(size);
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device instance ID");
> + goto out;
> + }
> + }
> +
> + /*
> + * CM API used here as opposed to
> + * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...)
> + * which exports are only available in mingw-w64 6+
> + */
> + cr = CM_Locate_DevInst(&dev_inst, parent_dev_id, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Locate_DevInst failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device instance");
> + goto out;
> + }
> + cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Parent failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device instance");
> + goto out;
> + }
> +
> + cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Device_ID_Size failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device ID length");
> + goto out;
> + }
> +
> + ++dev_id_size;
> + if (dev_id_size > size) {
> + g_free(parent_dev_id);
> + parent_dev_id = g_malloc(dev_id_size);
> + }
> +
> + cr = CM_Get_Device_ID(parent_dev_inst, parent_dev_id, dev_id_size,
> + 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Device_ID failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device ID");
> + goto out;
> + }
> }
>
> - /* The function retrieves the device's address. This value will be
> - * transformed into device function and number */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
> - debug_error("failed to get address");
> - addr = -1;
> - partial_pci = true;
> + g_debug("querying storage controller %s for PCI information",
> + parent_dev_id);
> + parent_dev_info =
> + SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id,
> + NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
> + g_free(parent_dev_id);
> +
> + if (parent_dev_info == INVALID_HANDLE_VALUE) {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device");
> + goto out;
> }
>
> - /* This call returns UINumber of DEVICE_CAPABILITIES structure.
> - * This number is typically a user-perceived slot number. */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
> - debug_error("failed to get slot");
> - slot = -1;
> - partial_pci = true;
> + parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
> + if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device data");
> + goto out;
> }
>
> - /* SetupApi gives us the same information as driver with
> - * IoGetDeviceProperty. According to Microsoft
> - * https://support.microsoft.com/en-us/kb/253232
> - * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
> - * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
> - * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
> -
> - if (partial_pci) {
> - pci->domain = -1;
> - pci->slot = -1;
> - pci->function = -1;
> - pci->bus = -1;
> - } else {
> - func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF;
> - dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
> - pci->domain = dev;
> - pci->slot = (int) slot;
> - pci->function = func;
> - pci->bus = (int) bus;
> + for (j = 0;
> + SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
> + j++) {
> + DWORD addr, bus, slot, type;
> + int func, dev;
> +
> + /* There is no need to allocate buffer in the next functions. The size
> + * is known and ULONG according to
> + * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
> + */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
> + &type, (PBYTE)&bus, size, NULL)) {
> + debug_error("failed to get PCI bus");
> + bus = -1;
> + partial_pci = true;
> + }
> +
> + /* The function retrieves the device's address. This value will be
> + * transformed into device function and number */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
> + &type, (PBYTE)&addr, size, NULL)) {
> + debug_error("failed to get PCI address");
> + addr = -1;
> + partial_pci = true;
> + }
> +
> + /* This call returns UINumber of DEVICE_CAPABILITIES structure.
> + * This number is typically a user-perceived slot number. */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
> + &type, (PBYTE)&slot, size, NULL)) {
> + debug_error("failed to get PCI slot");
> + slot = -1;
> + partial_pci = true;
> + }
> +
> + /* SetupApi gives us the same information as driver with
> + * IoGetDeviceProperty. According to Microsoft
> + * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
> + * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
> + * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
> + * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
> +
> + if (partial_pci) {
> + pci->domain = -1;
> + pci->slot = -1;
> + pci->function = -1;
> + pci->bus = -1;
> + continue;
> + } else {
> + func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
> + dev = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
> + pci->domain = dev;
> + pci->slot = (int)slot;
> + pci->function = func;
> + pci->bus = (int)bus;
> + break;
> + }
> }
> + SetupDiDestroyDeviceInfoList(parent_dev_info);
> break;
> }
>
> free_dev_info:
> SetupDiDestroyDeviceInfoList(dev_info);
> out:
> - g_free(buffer);
> - g_free(name);
> return pci;
> }
>
> @@ -720,7 +812,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
> * if that doesn't hold since that suggests some other unexpected
> * breakage
> */
> - disk->pci_controller = get_pci_info(disk->dev, &local_err);
> + disk->pci_controller = get_pci_info(disk->number, &local_err);
> if (local_err) {
> error_propagate(errp, local_err);
> goto err_close;
> @@ -736,7 +828,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
> /* We are able to use the same ioctls for different bus types
> * according to Microsoft docs
> * https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */
> - g_debug("getting pci-controller info");
> + g_debug("getting SCSI info");
> if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
> sizeof(SCSI_ADDRESS), &len, NULL)) {
> disk->unit = addr.Lun;
> @@ -838,8 +930,9 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
> * https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#win32-device-namespaces
> */
> disk->has_dev = true;
> + disk->number = extents->Extents[i].DiskNumber;
> disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
> - extents->Extents[i].DiskNumber);
> + extents->Extents[i].DiskNumber);
Do we really need an additional OS-specific 'number' field if it is already
encoded in the OS-specific disk->dev path?
Also this part seems like a seperate patch that is unrelated to fixing PCI
address reporting. If the 2 cannot be seperated please explain why in
the commit log.
Also please provide a basic summary of what your patch is doing in the commit
log. We generally expect this for anything other than trivial patches.
Thank you for working on fixing this.
>
> get_single_disk_info(disk, &local_err);
> if (local_err) {
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index c6725b3ec8..0a78fb2e3a 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -836,6 +836,7 @@
> # @unit: unit id
> # @serial: serial number (since: 3.1)
> # @dev: device node (POSIX) or device UNC (Windows) (since: 3.1)
> +# @number: device slot index (Windows)
> #
> # Since: 2.2
> ##
> @@ -843,7 +844,7 @@
> 'data': {'pci-controller': 'GuestPCIAddress',
> 'bus-type': 'GuestDiskBusType',
> 'bus': 'int', 'target': 'int', 'unit': 'int',
> - '*serial': 'str', '*dev': 'str'} }
> + '*serial': 'str', '*dev': 'str', 'number':'int'} }
>
> ##
> # @GuestFilesystemInfo:
> --
> 2.11.0.windows.1
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection inWindows
2019-01-24 17:56 ` [Qemu-devel] [PATCH] " Michael Roth
@ 2019-01-24 17:59 ` Matt Hines
0 siblings, 0 replies; 12+ messages in thread
From: Matt Hines @ 2019-01-24 17:59 UTC (permalink / raw)
To: Michael Roth, qemu-devel
Patch v2 removed the device number and added a summary
From: Michael Roth
Sent: Thursday, January 24, 2019 9:56
To: mhines@scalecomputing.com; qemu-devel@nongnu.org
Cc: Matt Hines
Subject: Re: [PATCH] QGA: Fix guest-get-fsinfo PCI address collection inWindows
Quoting mhines@scalecomputing.com (2019-01-14 03:03:23)
> From: Matt Hines <mhines@scalecomputing.com>
>
> Signed-off-by: Matt Hines <mhines@scalecomputing.com>
> ---
> configure | 2 +-
> qga/commands-win32.c | 295 +++++++++++++++++++++++++++++++++------------------
> qga/qapi-schema.json | 3 +-
> 3 files changed, 197 insertions(+), 103 deletions(-)
>
> diff --git a/configure b/configure
> index 5b1d83ea26..46f21c089f 100755
> --- a/configure
> +++ b/configure
> @@ -4694,7 +4694,7 @@ int main(void) {
> EOF
> if compile_prog "" "" ; then
> guest_agent_ntddscsi=yes
> - libs_qga="-lsetupapi $libs_qga"
> + libs_qga="-lsetupapi -lcfgmgr32 $libs_qga"
> fi
> fi
>
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index 62e1b51dfe..8c8f3a2c65 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -26,6 +26,7 @@
> #include <winioctl.h>
> #include <ntddscsi.h>
> #include <setupapi.h>
> +#include <cfgmgr32.h>
> #include <initguid.h>
> #endif
> #include <lm.h>
> @@ -491,56 +492,29 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
> return win2qemu[(int)bus];
> }
>
> -/* XXX: The following function is BROKEN!
> - *
> - * It does not work and probably has never worked. When we query for list of
> - * disks we get cryptic names like "\Device\0000001d" instead of
> - * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one
> - * way or the other for comparison is an open question.
> - *
> - * When we query volume names (the original version) we are able to match those
> - * but then the property queries report error "Invalid function". (duh!)
> - */
> -
> -/*
> -DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
> - 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
> - 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
> -*/
> DEFINE_GUID(GUID_DEVINTERFACE_DISK,
> 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
> 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
> +DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
> + 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
> + 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
>
> -
> -static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
> +static GuestPCIAddress *get_pci_info(int number, Error **errp)
> {
> HDEVINFO dev_info;
> SP_DEVINFO_DATA dev_info_data;
> - DWORD size = 0;
> + SP_DEVICE_INTERFACE_DATA dev_iface_data;
> + HANDLE dev_file;
> int i;
> - char dev_name[MAX_PATH];
> - char *buffer = NULL;
> GuestPCIAddress *pci = NULL;
> - char *name = NULL;
> bool partial_pci = false;
> +
> pci = g_malloc0(sizeof(*pci));
> pci->domain = -1;
> pci->slot = -1;
> pci->function = -1;
> pci->bus = -1;
>
> - if (g_str_has_prefix(guid, "\\\\.\\") ||
> - g_str_has_prefix(guid, "\\\\?\\")) {
> - name = g_strdup(guid + 4);
> - } else {
> - name = g_strdup(guid);
> - }
> -
> - if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
> - error_setg_win32(errp, GetLastError(), "failed to get dos device name");
> - goto out;
> - }
> -
> dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
> DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
> if (dev_info == INVALID_HANDLE_VALUE) {
> @@ -550,90 +524,208 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
>
> g_debug("enumerating devices");
> dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
> + dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
> for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
> - DWORD addr, bus, slot, data, size2;
> - int func, dev;
> - while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
> - &data, (PBYTE)buffer, size,
> - &size2)) {
> - size = MAX(size, size2);
> - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> - g_free(buffer);
> - /* Double the size to avoid problems on
> - * W2k MBCS systems per KB 888609.
> - * https://support.microsoft.com/en-us/kb/259695 */
> - buffer = g_malloc(size * 2);
> - } else {
> + PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL;
> + STORAGE_DEVICE_NUMBER sdn;
> + char *parent_dev_id = NULL;
> + HDEVINFO parent_dev_info;
> + SP_DEVINFO_DATA parent_dev_info_data;
> + DWORD j;
> + DWORD size = 0;
> +
> + g_debug("getting device path");
> + if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data,
> + &GUID_DEVINTERFACE_DISK, 0,
> + &dev_iface_data)) {
> + while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data,
> + pdev_iface_detail_data,
> + size, &size,
> + &dev_info_data)) {
> + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> + pdev_iface_detail_data = g_malloc(size);
> + pdev_iface_detail_data->cbSize =
> + sizeof(*pdev_iface_detail_data);
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device interfaces");
> + goto free_dev_info;
> + }
> + }
> +
> + dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
> + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
> + NULL);
> + g_free(pdev_iface_detail_data);
> +
> + if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
> + NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
> + CloseHandle(dev_file);
> error_setg_win32(errp, GetLastError(),
> - "failed to get device name");
> + "failed to get device slot number");
> goto free_dev_info;
> }
> - }
>
> - if (g_strcmp0(buffer, dev_name)) {
> - continue;
> + CloseHandle(dev_file);
> + if (sdn.DeviceNumber != number) {
> + continue;
> + }
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device interfaces");
> + goto free_dev_info;
> }
> - g_debug("found device %s", dev_name);
>
> - /* There is no need to allocate buffer in the next functions. The size
> - * is known and ULONG according to
> - * https://support.microsoft.com/en-us/kb/253232
> - * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
> - */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
> - debug_error("failed to get bus");
> - bus = -1;
> - partial_pci = true;
> + g_debug("found device slot %d. Getting storage controller", number);
> + {
> + CONFIGRET cr;
> + DEVINST dev_inst, parent_dev_inst;
> + ULONG dev_id_size = 0;
> +
> + size = 0;
> + while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data,
> + parent_dev_id, size, &size)) {
> + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
> + parent_dev_id = g_malloc(size);
> + } else {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device instance ID");
> + goto out;
> + }
> + }
> +
> + /*
> + * CM API used here as opposed to
> + * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...)
> + * which exports are only available in mingw-w64 6+
> + */
> + cr = CM_Locate_DevInst(&dev_inst, parent_dev_id, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Locate_DevInst failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get device instance");
> + goto out;
> + }
> + cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Parent failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device instance");
> + goto out;
> + }
> +
> + cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Device_ID_Size failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device ID length");
> + goto out;
> + }
> +
> + ++dev_id_size;
> + if (dev_id_size > size) {
> + g_free(parent_dev_id);
> + parent_dev_id = g_malloc(dev_id_size);
> + }
> +
> + cr = CM_Get_Device_ID(parent_dev_inst, parent_dev_id, dev_id_size,
> + 0);
> + if (cr != CR_SUCCESS) {
> + g_error("CM_Get_Device_ID failed with code %lx", cr);
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device ID");
> + goto out;
> + }
> }
>
> - /* The function retrieves the device's address. This value will be
> - * transformed into device function and number */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
> - debug_error("failed to get address");
> - addr = -1;
> - partial_pci = true;
> + g_debug("querying storage controller %s for PCI information",
> + parent_dev_id);
> + parent_dev_info =
> + SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id,
> + NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
> + g_free(parent_dev_id);
> +
> + if (parent_dev_info == INVALID_HANDLE_VALUE) {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device");
> + goto out;
> }
>
> - /* This call returns UINumber of DEVICE_CAPABILITIES structure.
> - * This number is typically a user-perceived slot number. */
> - if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
> - SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
> - debug_error("failed to get slot");
> - slot = -1;
> - partial_pci = true;
> + parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
> + if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) {
> + error_setg_win32(errp, GetLastError(),
> + "failed to get parent device data");
> + goto out;
> }
>
> - /* SetupApi gives us the same information as driver with
> - * IoGetDeviceProperty. According to Microsoft
> - * https://support.microsoft.com/en-us/kb/253232
> - * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
> - * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
> - * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
> -
> - if (partial_pci) {
> - pci->domain = -1;
> - pci->slot = -1;
> - pci->function = -1;
> - pci->bus = -1;
> - } else {
> - func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF;
> - dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
> - pci->domain = dev;
> - pci->slot = (int) slot;
> - pci->function = func;
> - pci->bus = (int) bus;
> + for (j = 0;
> + SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
> + j++) {
> + DWORD addr, bus, slot, type;
> + int func, dev;
> +
> + /* There is no need to allocate buffer in the next functions. The size
> + * is known and ULONG according to
> + * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
> + */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
> + &type, (PBYTE)&bus, size, NULL)) {
> + debug_error("failed to get PCI bus");
> + bus = -1;
> + partial_pci = true;
> + }
> +
> + /* The function retrieves the device's address. This value will be
> + * transformed into device function and number */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
> + &type, (PBYTE)&addr, size, NULL)) {
> + debug_error("failed to get PCI address");
> + addr = -1;
> + partial_pci = true;
> + }
> +
> + /* This call returns UINumber of DEVICE_CAPABILITIES structure.
> + * This number is typically a user-perceived slot number. */
> + if (!SetupDiGetDeviceRegistryProperty(
> + parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
> + &type, (PBYTE)&slot, size, NULL)) {
> + debug_error("failed to get PCI slot");
> + slot = -1;
> + partial_pci = true;
> + }
> +
> + /* SetupApi gives us the same information as driver with
> + * IoGetDeviceProperty. According to Microsoft
> + * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
> + * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
> + * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
> + * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
> +
> + if (partial_pci) {
> + pci->domain = -1;
> + pci->slot = -1;
> + pci->function = -1;
> + pci->bus = -1;
> + continue;
> + } else {
> + func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
> + dev = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
> + pci->domain = dev;
> + pci->slot = (int)slot;
> + pci->function = func;
> + pci->bus = (int)bus;
> + break;
> + }
> }
> + SetupDiDestroyDeviceInfoList(parent_dev_info);
> break;
> }
>
> free_dev_info:
> SetupDiDestroyDeviceInfoList(dev_info);
> out:
> - g_free(buffer);
> - g_free(name);
> return pci;
> }
>
> @@ -720,7 +812,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
> * if that doesn't hold since that suggests some other unexpected
> * breakage
> */
> - disk->pci_controller = get_pci_info(disk->dev, &local_err);
> + disk->pci_controller = get_pci_info(disk->number, &local_err);
> if (local_err) {
> error_propagate(errp, local_err);
> goto err_close;
> @@ -736,7 +828,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
> /* We are able to use the same ioctls for different bus types
> * according to Microsoft docs
> * https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */
> - g_debug("getting pci-controller info");
> + g_debug("getting SCSI info");
> if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
> sizeof(SCSI_ADDRESS), &len, NULL)) {
> disk->unit = addr.Lun;
> @@ -838,8 +930,9 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
> * https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#win32-device-namespaces
> */
> disk->has_dev = true;
> + disk->number = extents->Extents[i].DiskNumber;
> disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
> - extents->Extents[i].DiskNumber);
> + extents->Extents[i].DiskNumber);
Do we really need an additional OS-specific 'number' field if it is already
encoded in the OS-specific disk->dev path?
Also this part seems like a seperate patch that is unrelated to fixing PCI
address reporting. If the 2 cannot be seperated please explain why in
the commit log.
Also please provide a basic summary of what your patch is doing in the commit
log. We generally expect this for anything other than trivial patches.
Thank you for working on fixing this.
>
> get_single_disk_info(disk, &local_err);
> if (local_err) {
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index c6725b3ec8..0a78fb2e3a 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -836,6 +836,7 @@
> # @unit: unit id
> # @serial: serial number (since: 3.1)
> # @dev: device node (POSIX) or device UNC (Windows) (since: 3.1)
> +# @number: device slot index (Windows)
> #
> # Since: 2.2
> ##
> @@ -843,7 +844,7 @@
> 'data': {'pci-controller': 'GuestPCIAddress',
> 'bus-type': 'GuestDiskBusType',
> 'bus': 'int', 'target': 'int', 'unit': 'int',
> - '*serial': 'str', '*dev': 'str'} }
> + '*serial': 'str', '*dev': 'str', 'number':'int'} }
>
> ##
> # @GuestFilesystemInfo:
> --
> 2.11.0.windows.1
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
` (3 preceding siblings ...)
2019-01-24 17:56 ` [Qemu-devel] [PATCH] " Michael Roth
@ 2019-01-28 22:30 ` mhines
2019-01-31 17:53 ` no-reply
4 siblings, 1 reply; 12+ messages in thread
From: mhines @ 2019-01-28 22:30 UTC (permalink / raw)
To: qemu-devel; +Cc: Matt Hines, Michael Roth
From: Matt Hines <mhines@scalecomputing.com>
The Windows QEMU guest agent erroneously tries to collect PCI information
directly from the physical drive. However, windows stores SCSI/IDE information
with the drive and PCI information with the underlying storage controller
This changes get_pci_info to use the physical drive's underlying storage
controller to get PCI information.
* Additionally Fixes incorrect size being passed to DeviceIoControl
when getting volume extents. Can occasionally crash the guest agent
Signed-off-by: Matt Hines <mhines@scalecomputing.com>
---
configure | 2 +-
qga/commands-win32.c | 305 +++++++++++++++++++++++++++++++++------------------
2 files changed, 199 insertions(+), 108 deletions(-)
diff --git a/configure b/configure
index 5b1d83ea26..46f21c089f 100755
--- a/configure
+++ b/configure
@@ -4694,7 +4694,7 @@ int main(void) {
EOF
if compile_prog "" "" ; then
guest_agent_ntddscsi=yes
- libs_qga="-lsetupapi $libs_qga"
+ libs_qga="-lsetupapi -lcfgmgr32 $libs_qga"
fi
fi
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 62e1b51dfe..5f8e797032 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -26,6 +26,7 @@
#include <winioctl.h>
#include <ntddscsi.h>
#include <setupapi.h>
+#include <cfgmgr32.h>
#include <initguid.h>
#endif
#include <lm.h>
@@ -491,56 +492,29 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
return win2qemu[(int)bus];
}
-/* XXX: The following function is BROKEN!
- *
- * It does not work and probably has never worked. When we query for list of
- * disks we get cryptic names like "\Device\0000001d" instead of
- * "\PhysicalDriveX" or "\HarddiskX". Whether the names can be translated one
- * way or the other for comparison is an open question.
- *
- * When we query volume names (the original version) we are able to match those
- * but then the property queries report error "Invalid function". (duh!)
- */
-
-/*
-DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
- 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
- 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-*/
DEFINE_GUID(GUID_DEVINTERFACE_DISK,
0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2,
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
+DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT,
+ 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82,
+ 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
-
-static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
+static GuestPCIAddress *get_pci_info(int number, Error **errp)
{
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_info_data;
- DWORD size = 0;
+ SP_DEVICE_INTERFACE_DATA dev_iface_data;
+ HANDLE dev_file;
int i;
- char dev_name[MAX_PATH];
- char *buffer = NULL;
GuestPCIAddress *pci = NULL;
- char *name = NULL;
bool partial_pci = false;
+
pci = g_malloc0(sizeof(*pci));
pci->domain = -1;
pci->slot = -1;
pci->function = -1;
pci->bus = -1;
- if (g_str_has_prefix(guid, "\\\\.\\") ||
- g_str_has_prefix(guid, "\\\\?\\")) {
- name = g_strdup(guid + 4);
- } else {
- name = g_strdup(guid);
- }
-
- if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
- error_setg_win32(errp, GetLastError(), "failed to get dos device name");
- goto out;
- }
-
dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (dev_info == INVALID_HANDLE_VALUE) {
@@ -550,90 +524,208 @@ static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
g_debug("enumerating devices");
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
- DWORD addr, bus, slot, data, size2;
- int func, dev;
- while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
- &data, (PBYTE)buffer, size,
- &size2)) {
- size = MAX(size, size2);
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- g_free(buffer);
- /* Double the size to avoid problems on
- * W2k MBCS systems per KB 888609.
- * https://support.microsoft.com/en-us/kb/259695 */
- buffer = g_malloc(size * 2);
- } else {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL;
+ STORAGE_DEVICE_NUMBER sdn;
+ char *parent_dev_id = NULL;
+ HDEVINFO parent_dev_info;
+ SP_DEVINFO_DATA parent_dev_info_data;
+ DWORD j;
+ DWORD size = 0;
+
+ g_debug("getting device path");
+ if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data,
+ &GUID_DEVINTERFACE_DISK, 0,
+ &dev_iface_data)) {
+ while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data,
+ pdev_iface_detail_data,
+ size, &size,
+ &dev_info_data)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ pdev_iface_detail_data = g_malloc(size);
+ pdev_iface_detail_data->cbSize =
+ sizeof(*pdev_iface_detail_data);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
+ }
+ }
+
+ dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,
+ NULL);
+ g_free(pdev_iface_detail_data);
+
+ if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
+ NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
+ CloseHandle(dev_file);
error_setg_win32(errp, GetLastError(),
- "failed to get device name");
+ "failed to get device slot number");
goto free_dev_info;
}
- }
- if (g_strcmp0(buffer, dev_name)) {
- continue;
+ CloseHandle(dev_file);
+ if (sdn.DeviceNumber != number) {
+ continue;
+ }
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device interfaces");
+ goto free_dev_info;
}
- g_debug("found device %s", dev_name);
- /* There is no need to allocate buffer in the next functions. The size
- * is known and ULONG according to
- * https://support.microsoft.com/en-us/kb/253232
- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
- */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
- debug_error("failed to get bus");
- bus = -1;
- partial_pci = true;
+ g_debug("found device slot %d. Getting storage controller", number);
+ {
+ CONFIGRET cr;
+ DEVINST dev_inst, parent_dev_inst;
+ ULONG dev_id_size = 0;
+
+ size = 0;
+ while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data,
+ parent_dev_id, size, &size)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ parent_dev_id = g_malloc(size);
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance ID");
+ goto out;
+ }
+ }
+
+ /*
+ * CM API used here as opposed to
+ * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...)
+ * which exports are only available in mingw-w64 6+
+ */
+ cr = CM_Locate_DevInst(&dev_inst, parent_dev_id, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Locate_DevInst failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device instance");
+ goto out;
+ }
+ cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Parent failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device instance");
+ goto out;
+ }
+
+ cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID_Size failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID length");
+ goto out;
+ }
+
+ ++dev_id_size;
+ if (dev_id_size > size) {
+ g_free(parent_dev_id);
+ parent_dev_id = g_malloc(dev_id_size);
+ }
+
+ cr = CM_Get_Device_ID(parent_dev_inst, parent_dev_id, dev_id_size,
+ 0);
+ if (cr != CR_SUCCESS) {
+ g_error("CM_Get_Device_ID failed with code %lx", cr);
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device ID");
+ goto out;
+ }
}
- /* The function retrieves the device's address. This value will be
- * transformed into device function and number */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
- debug_error("failed to get address");
- addr = -1;
- partial_pci = true;
+ g_debug("querying storage controller %s for PCI information",
+ parent_dev_id);
+ parent_dev_info =
+ SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id,
+ NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ g_free(parent_dev_id);
+
+ if (parent_dev_info == INVALID_HANDLE_VALUE) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device");
+ goto out;
}
- /* This call returns UINumber of DEVICE_CAPABILITIES structure.
- * This number is typically a user-perceived slot number. */
- if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
- SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
- debug_error("failed to get slot");
- slot = -1;
- partial_pci = true;
+ parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get parent device data");
+ goto out;
}
- /* SetupApi gives us the same information as driver with
- * IoGetDeviceProperty. According to Microsoft
- * https://support.microsoft.com/en-us/kb/253232
- * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
- * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
- * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
-
- if (partial_pci) {
- pci->domain = -1;
- pci->slot = -1;
- pci->function = -1;
- pci->bus = -1;
- } else {
- func = ((int) addr == -1) ? -1 : addr & 0x0000FFFF;
- dev = ((int) addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
- pci->domain = dev;
- pci->slot = (int) slot;
- pci->function = func;
- pci->bus = (int) bus;
+ for (j = 0;
+ SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data);
+ j++) {
+ DWORD addr, bus, slot, type;
+ int func, dev;
+
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
+ * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
+ */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER,
+ &type, (PBYTE)&bus, size, NULL)) {
+ debug_error("failed to get PCI bus");
+ bus = -1;
+ partial_pci = true;
+ }
+
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS,
+ &type, (PBYTE)&addr, size, NULL)) {
+ debug_error("failed to get PCI address");
+ addr = -1;
+ partial_pci = true;
+ }
+
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
+ if (!SetupDiGetDeviceRegistryProperty(
+ parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER,
+ &type, (PBYTE)&slot, size, NULL)) {
+ debug_error("failed to get PCI slot");
+ slot = -1;
+ partial_pci = true;
+ }
+
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
+ * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
+ * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
+ * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
+
+ if (partial_pci) {
+ pci->domain = -1;
+ pci->slot = -1;
+ pci->function = -1;
+ pci->bus = -1;
+ continue;
+ } else {
+ func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF;
+ dev = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF;
+ pci->domain = dev;
+ pci->slot = (int)slot;
+ pci->function = func;
+ pci->bus = (int)bus;
+ break;
+ }
}
+ SetupDiDestroyDeviceInfoList(parent_dev_info);
break;
}
free_dev_info:
SetupDiDestroyDeviceInfoList(dev_info);
out:
- g_free(buffer);
- g_free(name);
return pci;
}
@@ -691,7 +783,8 @@ out_free:
return;
}
-static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
+static void get_single_disk_info(int disk_number,
+ GuestDiskAddress *disk, Error **errp)
{
SCSI_ADDRESS addr, *scsi_ad;
DWORD len;
@@ -720,7 +813,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
* if that doesn't hold since that suggests some other unexpected
* breakage
*/
- disk->pci_controller = get_pci_info(disk->dev, &local_err);
+ disk->pci_controller = get_pci_info(disk_number, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto err_close;
@@ -736,7 +829,7 @@ static void get_single_disk_info(GuestDiskAddress *disk, Error **errp)
/* We are able to use the same ioctls for different bus types
* according to Microsoft docs
* https://technet.microsoft.com/en-us/library/ee851589(v=ws.10).aspx */
- g_debug("getting pci-controller info");
+ g_debug("getting SCSI info");
if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
sizeof(SCSI_ADDRESS), &len, NULL)) {
disk->unit = addr.Lun;
@@ -784,12 +877,10 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
size = sizeof(VOLUME_DISK_EXTENTS);
extents = g_malloc0(size);
if (!DeviceIoControl(vol_h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL,
- 0, extents, size, NULL, NULL)) {
+ 0, extents, size, &size, NULL)) {
DWORD last_err = GetLastError();
if (last_err == ERROR_MORE_DATA) {
/* Try once more with big enough buffer */
- size = sizeof(VOLUME_DISK_EXTENTS)
- + extents->NumberOfDiskExtents*sizeof(DISK_EXTENT);
g_free(extents);
extents = g_malloc0(size);
if (!DeviceIoControl(
@@ -805,7 +896,7 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
disk = g_malloc0(sizeof(GuestDiskAddress));
disk->has_dev = true;
disk->dev = g_strdup(name);
- get_single_disk_info(disk, &local_err);
+ get_single_disk_info(0xffffffff, disk, &local_err);
if (local_err) {
g_debug("failed to get disk info, ignoring error: %s",
error_get_pretty(local_err));
@@ -839,9 +930,9 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
*/
disk->has_dev = true;
disk->dev = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
- extents->Extents[i].DiskNumber);
+ extents->Extents[i].DiskNumber);
- get_single_disk_info(disk, &local_err);
+ get_single_disk_info(extents->Extents[i].DiskNumber, disk, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto out;
--
2.11.0.windows.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows
2019-01-28 22:30 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
@ 2019-01-31 17:53 ` no-reply
2019-02-28 1:41 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI addresscollection " Matt Hines
0 siblings, 1 reply; 12+ messages in thread
From: no-reply @ 2019-01-31 17:53 UTC (permalink / raw)
To: mhines; +Cc: fam, qemu-devel, mdroth
Patchew URL: https://patchew.org/QEMU/20190128223056.19452-1-mhines@scalecomputing.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Subject: [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows
Type: series
Message-id: 20190128223056.19452-1-mhines@scalecomputing.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
6805362916 QGA: Fix guest-get-fsinfo PCI address collection in Windows
=== OUTPUT BEGIN ===
WARNING: Block comments should align the * on each line
#198: FILE: qga/commands-win32.c:592:
+ /*
+ * CM API used here as opposed to
WARNING: line over 80 characters
#302: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments use a leading /* on a separate line
#302: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments should align the * on each line
#303: FILE: qga/commands-win32.c:662:
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
ERROR: spaces required around that '&' (ctx:VxV)
#308: FILE: qga/commands-win32.c:667:
+ &type, (PBYTE)&bus, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#326: FILE: qga/commands-win32.c:673:
+ /* The function retrieves the device's address. This value will be
WARNING: Block comments use a trailing */ on a separate line
#327: FILE: qga/commands-win32.c:674:
+ * transformed into device function and number */
WARNING: Block comments should align the * on each line
#327: FILE: qga/commands-win32.c:674:
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
ERROR: spaces required around that '&' (ctx:VxV)
#330: FILE: qga/commands-win32.c:677:
+ &type, (PBYTE)&addr, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#336: FILE: qga/commands-win32.c:683:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
WARNING: Block comments use a trailing */ on a separate line
#337: FILE: qga/commands-win32.c:684:
+ * This number is typically a user-perceived slot number. */
WARNING: Block comments should align the * on each line
#337: FILE: qga/commands-win32.c:684:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
ERROR: spaces required around that '&' (ctx:VxV)
#340: FILE: qga/commands-win32.c:687:
+ &type, (PBYTE)&slot, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#346: FILE: qga/commands-win32.c:693:
+ /* SetupApi gives us the same information as driver with
WARNING: Block comments should align the * on each line
#347: FILE: qga/commands-win32.c:694:
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
WARNING: Block comments use a trailing */ on a separate line
#351: FILE: qga/commands-win32.c:698:
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
total: 3 errors, 13 warnings, 407 lines checked
Commit 680536291660 (QGA: Fix guest-get-fsinfo PCI address collection in Windows) has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20190128223056.19452-1-mhines@scalecomputing.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI addresscollection in Windows
2019-01-31 17:53 ` no-reply
@ 2019-02-28 1:41 ` Matt Hines
0 siblings, 0 replies; 12+ messages in thread
From: Matt Hines @ 2019-02-28 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: fam, mdroth
ping
From: no-reply@patchew.org
Sent: Thursday, January 31, 2019 9:53
To: mhines@scalecomputing.com
Cc: fam@euphon.net; qemu-devel@nongnu.org; mhines@scalecomputing.com; mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI addresscollection in Windows
Patchew URL: https://patchew.org/QEMU/20190128223056.19452-1-mhines@scalecomputing.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Subject: [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows
Type: series
Message-id: 20190128223056.19452-1-mhines@scalecomputing.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
6805362916 QGA: Fix guest-get-fsinfo PCI address collection in Windows
=== OUTPUT BEGIN ===
WARNING: Block comments should align the * on each line
#198: FILE: qga/commands-win32.c:592:
+ /*
+ * CM API used here as opposed to
WARNING: line over 80 characters
#302: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments use a leading /* on a separate line
#302: FILE: qga/commands-win32.c:661:
+ /* There is no need to allocate buffer in the next functions. The size
WARNING: Block comments should align the * on each line
#303: FILE: qga/commands-win32.c:662:
+ /* There is no need to allocate buffer in the next functions. The size
+ * is known and ULONG according to
ERROR: spaces required around that '&' (ctx:VxV)
#308: FILE: qga/commands-win32.c:667:
+ &type, (PBYTE)&bus, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#326: FILE: qga/commands-win32.c:673:
+ /* The function retrieves the device's address. This value will be
WARNING: Block comments use a trailing */ on a separate line
#327: FILE: qga/commands-win32.c:674:
+ * transformed into device function and number */
WARNING: Block comments should align the * on each line
#327: FILE: qga/commands-win32.c:674:
+ /* The function retrieves the device's address. This value will be
+ * transformed into device function and number */
ERROR: spaces required around that '&' (ctx:VxV)
#330: FILE: qga/commands-win32.c:677:
+ &type, (PBYTE)&addr, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#336: FILE: qga/commands-win32.c:683:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
WARNING: Block comments use a trailing */ on a separate line
#337: FILE: qga/commands-win32.c:684:
+ * This number is typically a user-perceived slot number. */
WARNING: Block comments should align the * on each line
#337: FILE: qga/commands-win32.c:684:
+ /* This call returns UINumber of DEVICE_CAPABILITIES structure.
+ * This number is typically a user-perceived slot number. */
ERROR: spaces required around that '&' (ctx:VxV)
#340: FILE: qga/commands-win32.c:687:
+ &type, (PBYTE)&slot, size, NULL)) {
^
WARNING: Block comments use a leading /* on a separate line
#346: FILE: qga/commands-win32.c:693:
+ /* SetupApi gives us the same information as driver with
WARNING: Block comments should align the * on each line
#347: FILE: qga/commands-win32.c:694:
+ /* SetupApi gives us the same information as driver with
+ * IoGetDeviceProperty. According to Microsoft
WARNING: Block comments use a trailing */ on a separate line
#351: FILE: qga/commands-win32.c:698:
+ * SPDRP_ADDRESS is propertyAddress, so we do the same.*/
total: 3 errors, 13 warnings, 407 lines checked
Commit 680536291660 (QGA: Fix guest-get-fsinfo PCI address collection in Windows) has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20190128223056.19452-1-mhines@scalecomputing.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2019-02-28 1:41 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-14 9:03 [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
2019-01-14 9:24 ` no-reply
2019-01-14 19:41 ` Eric Blake
2019-01-14 20:37 ` [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI addresscollection " Matt Hines
2019-01-15 16:57 ` [Qemu-devel] [PATCH v2] QGA: Fix guest-get-fsinfo PCI address collection " mhines
2019-01-21 4:31 ` no-reply
2019-01-21 4:42 ` no-reply
2019-01-24 17:56 ` [Qemu-devel] [PATCH] " Michael Roth
2019-01-24 17:59 ` [Qemu-devel] [PATCH] QGA: Fix guest-get-fsinfo PCI address collection inWindows Matt Hines
2019-01-28 22:30 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI address collection in Windows mhines
2019-01-31 17:53 ` no-reply
2019-02-28 1:41 ` [Qemu-devel] [PATCH v3] QGA: Fix guest-get-fsinfo PCI addresscollection " Matt Hines
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.