@@ -16,6 +16,8 @@
#include <powrprof.h>
#include <stdio.h>
#include <string.h>
+#include <winioctl.h>
+#include <ntddscsi.h>
#include "qga/guest-agent-core.h"
#include "qga/vss-win32.h"
#include "qga-qmp-commands.h"
@@ -86,6 +88,44 @@ static OpenFlags *find_open_flag(const char *mode_str)
return NULL;
}
+typedef struct WinToLin {
+ STORAGE_BUS_TYPE win;
+ GuestDiskBusType lin;
+} WinToLin;
+
+static WinToLin buses[] = {
+ {BusTypeUnknown, GUEST_DISK_BUS_TYPE_UNKNOWN},
+ {BusTypeScsi, GUEST_DISK_BUS_TYPE_SCSI},
+ {BusTypeAtapi, GUEST_DISK_BUS_TYPE_IDE},
+ {BusTypeAta, GUEST_DISK_BUS_TYPE_IDE},
+ {BusType1394, GUEST_DISK_BUS_TYPE_1394},
+ {BusTypeSsa, GUEST_DISK_BUS_TYPE_SSA},
+ {BusTypeFibre, GUEST_DISK_BUS_TYPE_SSA},
+ {BusTypeUsb, GUEST_DISK_BUS_TYPE_USB},
+ {BusTypeRAID, GUEST_DISK_BUS_TYPE_RAID},
+#if (_WIN32_WINNT >= 0x0600)
+ {BusTypeiScsi, GUEST_DISK_BUS_TYPE_I_SCSI},
+ {BusTypeSas, GUEST_DISK_BUS_TYPE_SAS},
+ {BusTypeSata, GUEST_DISK_BUS_TYPE_SATA},
+ {BusTypeSd, GUEST_DISK_BUS_TYPE_SD},
+ {BusTypeMmc, GUEST_DISK_BUS_TYPE_MMC},
+ {BusTypeVirtual, GUEST_DISK_BUS_TYPE_VIRTUAL },
+ {BusTypeFileBackedVirtuaul, GUEST_DISK_BUS_TYPE_FBIRTUAL},
+ {BusTypeSpaces, GUEST_DISK_BUS_TYPE_SPACES}
+#endif
+};
+
+static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(buses); ++i) {
+ if (buses[i].win == bus) {
+ return buses[i].lin;
+ }
+ }
+ return GUEST_DISK_BUS_TYPE_MAX;
+}
+
static int64_t guest_file_handle_add(HANDLE fh, HANDLE pipe_other_end_fd,
Error **errp)
{
@@ -769,6 +809,91 @@ done:
return ge;
}
+static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
+{
+ return NULL;
+}
+
+static int get_disk_bus_type(HANDLE vol_h, Error **errp)
+{
+ STORAGE_PROPERTY_QUERY query;
+ STORAGE_DEVICE_DESCRIPTOR *dev_desc, buf;
+ DWORD received;
+
+ dev_desc = &buf;
+ dev_desc->Size = sizeof(buf);
+ query.PropertyId = StorageDeviceProperty;
+ query.QueryType = PropertyStandardQuery;
+
+ if (!DeviceIoControl(vol_h, IOCTL_STORAGE_QUERY_PROPERTY, &query,
+ sizeof(STORAGE_PROPERTY_QUERY), dev_desc, dev_desc->Size,
+ &received, NULL)) {
+ error_setg_win32(errp, GetLastError(), "failed to get bus type");
+ return -1;
+ }
+
+ return dev_desc->BusType;
+}
+
+static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
+{
+ /* VSS provider works with volumes, so there is no difference if
+ * the volume consist of spanned disks. As the result we can obtain
+ * info for first disk in the spanned disks group. */
+
+ GuestDiskAddressList *list;
+ GuestDiskAddress *disk;
+ SCSI_ADDRESS addr, *scsi_ad;
+ DWORD len;
+ int bus;
+ HANDLE vol_h;
+
+ scsi_ad = &addr;
+ char *name = g_strndup(guid, strlen(guid)-1);
+
+ vol_h = CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ 0, NULL);
+ if (vol_h == INVALID_HANDLE_VALUE) {
+ error_setg_win32(errp, GetLastError(), "failed to open volume");
+ return NULL;
+ }
+ g_free(name);
+ bus = get_disk_bus_type(vol_h, errp);
+ if (bus < 0) {
+ return NULL;
+ }
+ disk = g_malloc0(sizeof(*disk));
+ disk->bus_type = find_bus_type(bus);
+ if (bus == BusTypeScsi || bus == BusTypeAta || bus == BusTypeRAID
+#if (_WIN32_WINNT >= 0x0600)
+ /* This bus type is not supported before Windows Server 2003 SP1 */
+ || bus == BusTypeSas
+#endif
+ ) {
+ /* 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 */
+ if (DeviceIoControl(vol_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_ad,
+ sizeof(SCSI_ADDRESS), &len, NULL)) {
+ disk->unit = scsi_ad->Lun;
+ disk->target = scsi_ad->TargetId;
+ disk->bus = scsi_ad->PathId;
+ disk->pci_controller = get_pci_info(name, errp);
+ }
+ /* We do set error in this case, because we still have enough
+ * information about volume. */
+ } else {
+ disk->pci_controller = NULL;
+ }
+
+ list = g_malloc0(sizeof(*list));
+ list->value = disk;
+ list->next = NULL;
+ CloseHandle(vol_h);
+ return list;
+
+}
+
static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp)
{
DWORD info_size;
@@ -812,7 +937,7 @@ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp)
fs->name = g_strdup(guid);
fs->mountpoint = g_strndup(mnt_point, len);
fs->type = g_strdup(fs_name);
- fs->disk = NULL;
+ fs->disk = build_guest_disk_info(guid, errp);
g_free(mnt_point);
return fs;
@@ -711,6 +711,7 @@
# @GuestDiskBusType
#
# An enumeration of bus type of disks
+# is devided a bit on Linux and Windows guest
#
# @ide: IDE disks
# @fdc: floppy disks
@@ -721,12 +722,22 @@
# @uml: UML disks
# @sata: SATA disks
# @sd: SD cards
-#
+# @Unknown: Unknown bus type
+# @1394: Win IEEE 1394 bus type
+# @Ssa: Win SSA bus type
+# @Fibre: Win fiber channel bus type
+# @Raid: Win RAID bus type
+# @iScsi: Win iScsi bus type
+# @Sas: Win serial-attaches SCSI bus type
+# @Mmc: Win multimedia card (MMC) bus type
+# @Virtual: Win virtual bus type
+# @FB: Win file-backed bus type
# Since: 2.2
##
{ 'enum': 'GuestDiskBusType',
'data': [ 'ide', 'fdc', 'scsi', 'virtio', 'xen', 'usb', 'uml', 'sata',
- 'sd' ] }
+ 'sd', 'unknown', '1394','Ssa', 'fibre', 'RAID', 'iScsi', 'sas',
+ 'mmc', 'virtual', 'fbirtual' ] }
##
# @GuestPCIAddress: