From nobody Wed Nov 5 11:06:35 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 154029445030538.486546276313675; Tue, 23 Oct 2018 04:34:10 -0700 (PDT) Received: from localhost ([::1]:40322 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEuwj-0001bT-TD for importer@patchew.org; Tue, 23 Oct 2018 07:34:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42870) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEumm-0001sf-Aw for qemu-devel@nongnu.org; Tue, 23 Oct 2018 07:23:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gEumk-0007n9-II for qemu-devel@nongnu.org; Tue, 23 Oct 2018 07:23:44 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:39140) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gEumk-0007mL-59 for qemu-devel@nongnu.org; Tue, 23 Oct 2018 07:23:42 -0400 Received: by mail-wr1-f65.google.com with SMTP id r10-v6so363317wrv.6 for ; Tue, 23 Oct 2018 04:23:42 -0700 (PDT) Received: from localhost.localdomain (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id g8-v6sm1498990wmf.45.2018.10.23.04.23.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 23 Oct 2018 04:23:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KBurd7FjpCNqDHlBiPtRGCj5ouiHBlXtV4c/pDRqQ7w=; b=NDPe2n1xsPv6NuywxB5NVM3CcfjqGzCgc4Rdp6Yge72WyZ9DmGzCVfjdQO1lzJxBKP kQT7bqW9shNB6yJM2UTZrmaoQgOxh5lejBnAfUjQ1y6WWs4FRB4HhKjF/wc+BAqfPJPI kORtAC4H1NIWJP3Tj+X7NWQpQpNceMTLvCfDwPTp6hg9eVvLEfY4i9xWYckbGGWVldYu qXqBX2jUbMQaa6lmI1Sreqohz8Vxqya7Vu6Cvw+39wDriN7e/38Ej7cZICswqDr/az09 w5L2tBq18zmDPXbO7rX1rwI5nGJZGx12leCGeo7Kl/gS5nKihKXi324P2zrC+TSWxF6H WN6Q== X-Gm-Message-State: AGRZ1gISDzDTJ0H7GwK7HALT9Q52T8VBn+RO0yy+EmA5TkDWNKe4aIxa h9qBwB6+J5mNPzPDUbdOGQXsO5ppfWs= X-Google-Smtp-Source: AJdET5dvFBVxf5AtyFb+18d/vUxJuTWRFfo1KCZuzlxRRTzFYh3psN6Hv7yB0HY/Sw3e3W+sfDv9Bw== X-Received: by 2002:a5d:558b:: with SMTP id i11-v6mr5860683wrv.38.1540293820825; Tue, 23 Oct 2018 04:23:40 -0700 (PDT) From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= To: qemu-devel@nongnu.org Date: Tue, 23 Oct 2018 13:23:21 +0200 Message-Id: X-Mailer: git-send-email 2.19.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.221.65 Subject: [Qemu-devel] [PATCH v5 12/14] qga-win: handle multi-disk volumes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Olga Krishtal , =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= , Sameeh Jubran , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Probe the volume for disk extents and return list of all disks. Originally only first disk of composite volume was returned. Note that the patch changes get_pci_info() from one state of brokenness into a different state of brokenness. In other words it still does not do what it's supposed to do (see comment in code). If anyone knows how to fix it, please step in. Signed-off-by: Tom=C3=A1=C5=A1 Golembiovsk=C3=BD --- qga/commands-win32.c | 126 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 108 insertions(+), 18 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index bb9bf0218a..09566b3f47 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -477,9 +477,26 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE= bus) return win2qemu[(int)bus]; } =20 +/* 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); + =20 static GuestPCIAddress *get_pci_info(char *guid, Error **errp) { @@ -502,7 +519,7 @@ static GuestPCIAddress *get_pci_info(char *guid, Error = **errp) goto out; } =20 - dev_info =3D SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0, + dev_info =3D SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (dev_info =3D=3D INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), "failed to get devices tree= "); @@ -642,20 +659,20 @@ static void get_single_disk_info(char *name, GuestDis= kAddress *disk, { SCSI_ADDRESS addr, *scsi_ad; DWORD len; - HANDLE vol_h; + HANDLE disk_h; Error *local_err =3D NULL; =20 scsi_ad =3D &addr; =20 g_debug("getting disk info for: %s", name); - vol_h =3D CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + disk_h =3D CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (vol_h =3D=3D INVALID_HANDLE_VALUE) { - error_setg_win32(errp, GetLastError(), "failed to open volume"); - goto err; + if (disk_h =3D=3D INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to open disk"); + return; } =20 - get_disk_properties(vol_h, disk, &local_err); + get_disk_properties(disk_h, disk, &local_err); if (local_err) { error_propagate(errp, local_err); goto err_close; @@ -682,7 +699,7 @@ static void get_single_disk_info(char *name, GuestDiskA= ddress *disk, * according to Microsoft docs * https://technet.microsoft.com/en-us/library/ee851589(v=3Dws.10)= .aspx */ g_debug("getting pci-controller info"); - if (DeviceIoControl(vol_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_a= d, + if (DeviceIoControl(disk_h, IOCTL_SCSI_GET_ADDRESS, NULL, 0, scsi_= ad, sizeof(SCSI_ADDRESS), &len, NULL)) { disk->unit =3D addr.Lun; disk->target =3D addr.TargetId; @@ -693,8 +710,7 @@ static void get_single_disk_info(char *name, GuestDiskA= ddress *disk, } =20 err_close: - CloseHandle(vol_h); -err: + CloseHandle(disk_h); return; } =20 @@ -706,6 +722,10 @@ static GuestDiskAddressList *build_guest_disk_info(cha= r *guid, Error **errp) Error *local_err =3D NULL; GuestDiskAddressList *list =3D NULL, *cur_item =3D NULL; GuestDiskAddress *disk =3D NULL; + int i; + HANDLE vol_h; + DWORD size; + PVOLUME_DISK_EXTENTS extents =3D NULL; =20 /* strip final backslash */ char *name =3D g_strdup(guid); @@ -713,20 +733,90 @@ static GuestDiskAddressList *build_guest_disk_info(ch= ar *guid, Error **errp) name[strlen(name) - 1] =3D 0; } =20 - disk =3D g_malloc0(sizeof(GuestDiskAddress)); - get_single_disk_info(name, disk, &local_err); - if (local_err) { - error_propagate(errp, local_err); + g_debug("opening %s", name); + vol_h =3D CreateFile(name, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + 0, NULL); + if (vol_h =3D=3D INVALID_HANDLE_VALUE) { + error_setg_win32(errp, GetLastError(), "failed to open volume"); goto out; } =20 - cur_item =3D g_malloc0(sizeof(*list)); - cur_item->value =3D disk; - disk =3D NULL; - list =3D cur_item; + /* Get list of extents */ + g_debug("getting disk extents"); + size =3D sizeof(VOLUME_DISK_EXTENTS); + extents =3D g_malloc0(size); + if (!DeviceIoControl(vol_h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, + 0, extents, size, NULL, NULL)) { + DWORD last_err =3D GetLastError(); + if (last_err =3D=3D ERROR_MORE_DATA) { + /* Try once more with big enough buffer */ + size =3D sizeof(VOLUME_DISK_EXTENTS) + + extents->NumberOfDiskExtents*sizeof(DISK_EXTENT); + g_free(extents); + extents =3D g_malloc0(size); + if (!DeviceIoControl( + vol_h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, + 0, extents, size, NULL, NULL)) { + error_setg_win32(errp, GetLastError(), + "failed to get disk extents"); + return NULL; + } + } else if (last_err =3D=3D ERROR_INVALID_FUNCTION) { + /* Possibly CD-ROM or a shared drive. Try to pass the volume */ + g_debug("volume not on disk"); + disk =3D g_malloc0(sizeof(GuestDiskAddress)); + get_single_disk_info(name, disk, &local_err); + if (local_err) { + g_debug("failed to get disk info, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); + goto out; + } + list =3D g_malloc0(sizeof(*list)); + list->value =3D disk; + disk =3D NULL; + list->next =3D NULL; + goto out; + } else { + error_setg_win32(errp, GetLastError(), + "failed to get disk extents"); + goto out; + } + } + g_debug("Number of extents: %lu", extents->NumberOfDiskExtents); + + /* Go through each extent */ + for (i =3D 0; i < extents->NumberOfDiskExtents; i++) { + char *disk_name =3D NULL; + disk =3D g_malloc0(sizeof(GuestDiskAddress)); + + /* Disk numbers directly correspond to numbers used in UNCs + * + * See documentation for DISK_EXTENT: + * https://docs.microsoft.com/en-us/windows/desktop/api/winioctl/n= s-winioctl-_disk_extent + * + * See also Naming Files, Paths and Namespaces: + * https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-= a-file#win32-device-namespaces + */ + disk_name =3D g_strdup_printf("\\\\.\\PhysicalDrive%lu", + extents->Extents[i].DiskNumber); + get_single_disk_info(disk_name, disk, &local_err); + g_free(disk_name); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + cur_item =3D g_malloc0(sizeof(*list)); + cur_item->value =3D disk; + disk =3D NULL; + cur_item->next =3D list; + list =3D cur_item; + } + =20 out: qapi_free_GuestDiskAddress(disk); + g_free(extents); g_free(name); =20 return list; --=20 2.19.0