From nobody Sat Feb 7 08:07:45 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1596704822; cv=none; d=zohomail.com; s=zohoarc; b=fy61E9kqwlAP/Zk6PuAJ2zwxHpzz2Nb9lWm24ButwHOlw9WW/QkAOZX0/PNRGF/4KbYhS5dya+HaCGIUbpjyryObogx+n7SFosiXIgegmz6SASRbZ//b2wAfzEgytKJsad35mxj8neDMBP2iJtISJBRtvtyFx7JmMHSrAQiwgfI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596704822; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=lGxLKgUNvUTwLjwqCcrfUUVls/sXJ3WF/pkHfkqfgsM=; b=NJANQp6rHZAenmzpaJ8YRg5XAyOS1XzX4YPSbF5sfnHfgRXCIH7syjCprYRw0VSO+7vo1Zpo1C/uQHCC9umyl+yJVC6AHbQFVi7wU7B6UIHhPQx7LazYrVtOkhzL4KVRRIC8xoiFhPgGe+y3Wg3V7ouZcKv2GYWCwSmVQ6DJYsM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596704822538769.602258265875; Thu, 6 Aug 2020 02:07:02 -0700 (PDT) Received: from localhost ([::1]:60800 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k3brZ-0001m2-7R for importer@patchew.org; Thu, 06 Aug 2020 05:07:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45936) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k3bp3-0007p1-RL for qemu-devel@nongnu.org; Thu, 06 Aug 2020 05:04:25 -0400 Received: from us-smtp-2.mimecast.com ([205.139.110.61]:49012 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1k3bp1-0003lJ-Np for qemu-devel@nongnu.org; Thu, 06 Aug 2020 05:04:25 -0400 Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-112-9wKG6BfWP76K6BCYkz8UDQ-1; Thu, 06 Aug 2020 05:03:11 -0400 Received: by mail-ej1-f69.google.com with SMTP id bx27so13634543ejc.15 for ; Thu, 06 Aug 2020 02:03:10 -0700 (PDT) Received: from auriga.redhat.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id g24sm3035681eds.42.2020.08.06.02.03.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2020 02:03:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1596704662; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lGxLKgUNvUTwLjwqCcrfUUVls/sXJ3WF/pkHfkqfgsM=; b=acZr2suNGTYP/rk/qs5WYyqHH+T2YWyBCcSX2/fJY3cKCaFkT2WGURkH62gblDzkN0ZQNT Qe7QJ/Rhy/ZNxoLVYLl6l/X1JrpwzRfdIQ27IpP9d5JjFcR36Ke93TJ6gC0qP9rIH6wP00 ljMro7QqEJgxaNv0lgDLbaWwT7FwuU8= X-MC-Unique: 9wKG6BfWP76K6BCYkz8UDQ-1 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=lGxLKgUNvUTwLjwqCcrfUUVls/sXJ3WF/pkHfkqfgsM=; b=HHrVp2rR0ZSMwK51xuFzA/Vvo7cAwBl+VuTLoi3KAYC+I8E/A2cotjw8PEDp/QMLo6 hI3f4p9EFH2iqROlUozSW2+opeIl6QayzUk/IBS0FUYi3PWGHSj2c26hzbEAJs0KvHVW cxJCq4ct91wnE3k3coOX7wLrJHEluclMI3KoU/cmRsVE8ykI6zt7HEUjNVnYT/+DOWnT flXBJzzrZfnU5XaDcrHC1mcuZxQMFq8grg3r+rhOvzIvdUlpp8itzGJlAoW8LxFMPZDa kH8FVeYJp3ezlqfSTWNuFjnjn2lAnuqFM8qRNZApwo+gzBl1e0upZ3OMScPGaxGJFg2a 6hfQ== X-Gm-Message-State: AOAM533GiKc6vj8o59cXQsrKH4/qbyl1cQTW2xPiMaCTgtIWjtDQVubN m0Rerk7JmS0MipNGm/xnyTA14wft2yvSSRDKhJ5L4qPsSV04Igyve07J/9kg9Tjbtr0GkHnwzFH eQz8qsfr/bohKLSQ= X-Received: by 2002:a17:906:d8b6:: with SMTP id qc22mr3503467ejb.468.1596704589556; Thu, 06 Aug 2020 02:03:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwiH88D69hml+secf0W5VwI2l/HmBzE1+34jp/oO8RRGhgm4IMfRoCEkd860S5kejp1O/IUxA== X-Received: by 2002:a17:906:d8b6:: with SMTP id qc22mr3503444ejb.468.1596704589318; Thu, 06 Aug 2020 02:03:09 -0700 (PDT) From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= To: Thomas Huth , Michael Roth , qemu-devel@nongnu.org Subject: [PATCH 1/1] qga: add command guest-get-disks Date: Thu, 6 Aug 2020 11:03:06 +0200 Message-Id: X-Mailer: git-send-email 2.25.0 In-Reply-To: References: MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=tgolembi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=205.139.110.61; envelope-from=tgolembi@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/06 00:07:42 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @redhat.com) The command guest-get-fsinfo can be used to list information about disks and partitions but it is limited only to mounted disks with filesystem. This new command allows listing information about attached root disks of the VM. Thi= s is usefull for management applications for mapping virtualized devices or pass-through devices to device names in the guest OS. Output is similar to the list of partitions of guest-get-fsinfo, except that the disks are mapped instead of partitions. Example output: { "return": [ { "serial": "SAMSUNG_123456789", "bus-type": "sata", "bus": 0, "unit": 0, "pci-controller": { "bus": 0, "slot": 31, "domain": 0, "function": 2 }, "dev": "/dev/sda", "target": 0 }, ... ] } Signed-off-by: Tom=C3=A1=C5=A1 Golembiovsk=C3=BD --- qga/commands-posix.c | 91 +++++++++++++++++++++++++++++++++++++++++++- qga/commands-win32.c | 83 ++++++++++++++++++++++++++++++++++++++++ qga/qapi-schema.json | 13 +++++++ 3 files changed, 186 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 744c2b5a5d..4cebec96a6 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -62,6 +62,8 @@ extern char **environ; #endif #endif =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GuestFilesystemInfo, qapi_free_GuestFilesyst= emInfo) + static void ga_wait_child(pid_t pid, int *status, Error **errp) { pid_t rpid; @@ -1177,6 +1179,92 @@ static void build_guest_fsinfo_for_device(char const= *devpath, free(syspath); } =20 +GuestDiskAddressList *qmp_guest_get_disks(Error **errp) +{ + GuestDiskAddressList *item, *ret =3D NULL; + DIR *dp =3D NULL; + struct dirent *de =3D NULL; + + g_debug("listing /sys/block directory"); + dp =3D opendir("/sys/block"); + if (dp =3D=3D NULL) { + error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"= "); + return NULL; + } + while ((de =3D readdir(dp)) !=3D NULL) { + g_autofree char *disk_dir =3D NULL, *line =3D NULL, + *size_path =3D NULL, *slaves_dir =3D NULL; + g_autoptr(GuestFilesystemInfo) fs =3D NULL; + uint64_t slaves =3D 0; + struct dirent *de_slaves; + DIR *dp_slaves =3D NULL; + FILE *fp =3D NULL; + size_t n; + Error *local_err =3D NULL; + if (de->d_type !=3D DT_LNK) { + g_debug(" skipping entry: %s", de->d_name); + continue; + } + + slaves_dir =3D g_strdup_printf("/sys/block/%s/slaves", de->d_name); + if (slaves_dir =3D=3D NULL) { + g_debug(" failed to open directory %s", slaves_dir); + continue; + } + g_debug(" counting entries in: %s", slaves_dir); + dp_slaves =3D opendir(slaves_dir); + while ((de_slaves =3D readdir(dp_slaves)) !=3D NULL) { + if ((strcmp(".", de_slaves->d_name) =3D=3D 0) || + (strcmp("..", de_slaves->d_name) =3D=3D 0)) { + continue; + } + slaves++; + } + closedir(dp_slaves); + g_debug(" counted %lu items", slaves); + if (slaves !=3D 0) { + continue; + } + + g_debug(" checking disk size"); + size_path =3D g_strdup_printf("/sys/block/%s/size", de->d_name); + fp =3D fopen(size_path, "r"); + if (!fp) { + g_debug(" failed to read disk size"); + continue; + } + if (getline(&line, &n, fp) =3D=3D -1) { + g_debug(" failed to read disk size"); + fclose(fp); + continue; + } + fclose(fp); + if (strcmp(line, "0\n") =3D=3D 0) { + g_debug(" skipping zero-sized disk"); + continue; + } + + fs =3D g_malloc0(sizeof(*fs)); + g_debug(" adding %s", de->d_name); + disk_dir =3D g_strdup_printf("/sys/block/%s", de->d_name); + build_guest_fsinfo_for_device(disk_dir, fs, &local_err); + if (local_err !=3D NULL) { + g_debug(" failed to get device info, ignoring error: %s", + error_get_pretty(local_err)); + error_free(local_err); + continue; + } else if (fs->disk =3D=3D NULL) { + g_debug(" skipping unknown disk"); + continue; + } + item =3D g_steal_pointer(&fs->disk); + g_assert(item->next =3D=3D NULL); /* expecting just a single disk = */ + item->next =3D ret; + ret =3D item; + } + return ret; +} + /* Return a list of the disk device(s)' info which @mount lies on */ static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, Error **errp) @@ -2809,7 +2897,8 @@ GList *ga_command_blacklist_init(GList *blacklist) const char *list[] =3D { "guest-get-fsinfo", "guest-fsfreeze-status", "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", - "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL}; + "guest-fsfreeze-thaw", "guest-get-fsinfo", + "guest-get-disks", NULL}; char **p =3D (char **)list; =20 while (*p) { diff --git a/qga/commands-win32.c b/qga/commands-win32.c index aaa71f147b..0bafa2dc4c 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -945,6 +945,83 @@ out: return list; } =20 +GuestDiskAddressList *qmp_guest_get_disks(Error **errp) +{ + GuestDiskAddressList *new =3D NULL, *ret =3D NULL; + HDEVINFO dev_info; + SP_DEVICE_INTERFACE_DATA dev_iface_data; + int i; + + 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 device tree"= ); + return NULL; + } + + g_debug("enumerating devices"); + dev_iface_data.cbSize =3D sizeof(SP_DEVICE_INTERFACE_DATA); + for (i =3D 0; + SetupDiEnumDeviceInterfaces(dev_info, NULL, &GUID_DEVINTERFACE_DIS= K, + i, &dev_iface_data); + i++) { + GuestDiskAddress *disk =3D NULL; + Error *local_err =3D NULL; + g_autofree PSP_DEVICE_INTERFACE_DETAIL_DATA + pdev_iface_detail_data =3D NULL; + STORAGE_DEVICE_NUMBER sdn; + HANDLE dev_file; + DWORD size =3D 0; + + g_debug(" getting device path"); + while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data, + pdev_iface_detail_data, + size, &size, + NULL)) { + if (GetLastError() =3D=3D ERROR_INSUFFICIENT_BUFFER) { + pdev_iface_detail_data =3D g_malloc(size); + pdev_iface_detail_data->cbSize =3D + sizeof(*pdev_iface_detail_data); + } else { + g_debug("failed to get device interface details"); + continue; + } + } + + g_debug(" device: %s", pdev_iface_detail_data->DevicePath); + dev_file =3D CreateFile(pdev_iface_detail_data->DevicePath, 0, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, 0, &sdn, sizeof(sdn), &size, NULL)) { + CloseHandle(dev_file); + debug_error("failed to get storage device number"); + continue; + } + CloseHandle(dev_file); + + g_debug(" number: %lu", sdn.DeviceNumber); + disk =3D g_malloc0(sizeof(GuestDiskAddress)); + disk->has_dev =3D true; + disk->dev =3D g_strdup_printf("\\\\.\\PhysicalDrive%lu", + sdn.DeviceNumber); + get_single_disk_info(sdn.DeviceNumber, disk, &local_err); + if (local_err) { + g_debug("failed to get disk info: %s", + error_get_pretty(local_err)); + error_free(local_err); + g_free(disk); + continue; + } + new =3D g_malloc0(sizeof(GuestDiskAddressList)); + new->value =3D disk; + new->next =3D ret; + ret =3D new; + } + + SetupDiDestroyDeviceInfoList(dev_info); + return ret; +} + #else =20 static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **err= p) @@ -952,6 +1029,12 @@ static GuestDiskAddressList *build_guest_disk_info(ch= ar *guid, Error **errp) return NULL; } =20 +GuestDiskAddressList *qmp_guest_get_disks(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + return NULL; +} + #endif /* CONFIG_QGA_NTDDSCSI */ =20 static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp) diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 408a662ea5..5d8fa1c283 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -862,6 +862,19 @@ 'bus': 'int', 'target': 'int', 'unit': 'int', '*serial': 'str', '*dev': 'str'} } =20 +## +# @guest-get-disks: +# +# Returns: The list of disks in the guest. For Windows these are only the +# physical disks. On Linux these are all root block devices of +# non-zero size including e.g. removable devices, loop devices, +# NBD, etc. +# +# Since: 5.2 +## +{ 'command': 'guest-get-disks', + 'returns': ['GuestDiskAddress'] } + ## # @GuestFilesystemInfo: # --=20 2.25.0