From nobody Mon Apr 29 02:01:29 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1658248447; cv=none; d=zohomail.com; s=zohoarc; b=IYNas/CwQJ5hv/IbZf21mbc2z5nnd6t+psCHB3iOaF533fTYL47oY/rXxG3m5XwAKenj2WNNAiTbL5k1T5OMnjnGZBj1rRwnvnMOaaBesGk2mR/WV4VWMjAQPNu1q9DRxfFRSo4ctd06DemMKlkq9mAjj2DQCbORVl+gzSPUROM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1658248447; h=Content-Type:Content-Transfer-Encoding:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=u7gWSaGXGLMLni4fbeAbmPgXGXzZooLIvwR1f/JC20I=; b=S6CEW14MVVdtZHX3h9mRzbXIlDlyPP25nvNOZhTyexW7BolVL+xi2o3Fp5r7POWlAYWIkqi0PkazM4IetasO/ufYx+UaUGqwzqxdPVzUeVI2W6DO4/3ItHL45L9noiJz2E1VuNWRNMOhkM3OqstpyP52BvCnCymTawhxcBwFpyg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1658248447083905.9065115131752; Tue, 19 Jul 2022 09:34:07 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-156-SiC1B-HrOh2CYzgfct-G7A-1; Tue, 19 Jul 2022 12:34:02 -0400 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id D10E52806AAE; Tue, 19 Jul 2022 16:33:59 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 64D7D492CA5; Tue, 19 Jul 2022 16:33:58 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 1F4E81947070; Tue, 19 Jul 2022 16:33:58 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 69A1C1945DA7 for ; Tue, 19 Jul 2022 16:33:57 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 5C45F404754B; Tue, 19 Jul 2022 16:33:57 +0000 (UTC) Received: from himantopus.redhat.com (unknown [10.22.32.197]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 33C3640CFD0A for ; Tue, 19 Jul 2022 16:33:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1658248445; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=u7gWSaGXGLMLni4fbeAbmPgXGXzZooLIvwR1f/JC20I=; b=DapQI6PYGZed0jubuu2U074mYHO2xOf/nYDS3xyTsMPmJuYU7JhaChXuSNyMOae4cPNOe3 siL+BDBcZyOwRgzDZpiX4PiUBG3CietxAfjMg/PbKgzJjqRKrMF1y0XCuoi0Wldjv1JMET ipAAeLJxj/zC3VV9s6rIQ3NQdjOUxXU= X-MC-Unique: SiC1B-HrOh2CYzgfct-G7A-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Jonathon Jongsma To: libvir-list@redhat.com Subject: [libvirt PATCH] nodedev: support 'mtty' device for testing Date: Tue, 19 Jul 2022 11:33:56 -0500 Message-Id: <20220719163356.337159-1-jjongsma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.1 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 2.85 on 10.11.54.9 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1658248448186100001 Content-Type: text/plain; charset="utf-8"; x-default="true" It would be nice to be able to test the mediated device capabilities without having physical hardware which supports it. The 'mtty' kernel module presents a virtual parent device which is capable of creating 'fake' mediated devices, and as such it would be useful for testing. However, the 'mtty' device is not part of an existing device subsystem (e.g. PCI, etc), so libvirt ignores it and it does not get added to the node device list. And because it does not get added to the node device list, it cannot be used to create child mdevs using `virsh nodedev-create`. There is already a node device type capability VIR_NODE_DEV_CAP_MDEV_TYPES that indicates whether a device supports creating child mediated devices, but libvirt assumes that this is a nested capability (in other words, it assumes that the primary capability of a device is something like PCI). If we allow this MDEV_TYPES capability to be a primary device capability, then we can support virtual devices like 'mtty' as a parent for mediated devices. See https://bugzilla.redhat.com/show_bug.cgi?id=3D2107031 Signed-off-by: Jonathon Jongsma Reviewed-by: Michal Privoznik --- src/conf/node_device_conf.c | 41 +++++++++++++++++++++++++++- src/conf/node_device_conf.h | 13 +++++++++ src/libvirt_private.syms | 2 ++ src/node_device/node_device_driver.c | 5 +++- src/node_device/node_device_udev.c | 25 +++++++++++++++++ src/util/virmdev.c | 28 +++++++++++++++++++ src/util/virmdev.h | 4 +++ 7 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 364bb489bd..d5bfc098b2 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -772,6 +772,10 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def) data->ap_matrix.nmdev_type= s); break; case VIR_NODE_DEV_CAP_MDEV_TYPES: + virNodeDeviceCapMdevTypesFormat(&buf, + data->mdev_parent.mdev_types, + data->mdev_parent.nmdev_types); + break; case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPD: @@ -2674,6 +2678,11 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps) g_free(data->ap_matrix.mdev_types); break; case VIR_NODE_DEV_CAP_MDEV_TYPES: + for (i =3D 0; i < data->mdev_parent.nmdev_types; i++) + virMediatedDeviceTypeFree(data->mdev_parent.mdev_types[i]); + g_free(data->mdev_parent.mdev_types); + g_free(data->mdev_parent.address); + break; case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: @@ -2729,6 +2738,11 @@ virNodeDeviceUpdateCaps(virNodeDeviceDef *def) &cap->data.ap_matrix) = < 0) return -1; break; + case VIR_NODE_DEV_CAP_MDEV_TYPES: + if (virNodeDeviceGetMdevParentDynamicCaps(def->sysfs_path, + &cap->data.mdev_pare= nt) < 0) + return -1; + break; =20 /* all types that (supposedly) don't require any updates * relative to what's in the cache. @@ -2742,7 +2756,6 @@ virNodeDeviceUpdateCaps(virNodeDeviceDef *def) case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_SCSI_GENERIC: - case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_VDPA: @@ -3193,6 +3206,24 @@ virNodeDeviceGetAPMatrixDynamicCaps(const char *sysf= sPath, return 0; } =20 +/* virNodeDeviceGetMdevParentDynamicCaps() get info that is stored in sysfs + * about devices related to this device, i.e. things that can change + * without this device itself changing. These must be refreshed + * anytime full XML of the device is requested, because they can + * change with no corresponding notification from the kernel/udev. + */ +int +virNodeDeviceGetMdevParentDynamicCaps(const char *sysfsPath, + virNodeDevCapMdevParent *mdev_parent) +{ + if (virNodeDeviceGetMdevTypesCaps(sysfsPath, + &mdev_parent->mdev_types, + &mdev_parent->nmdev_types) < 0) + return -1; + return 0; +} + + #else =20 int @@ -3229,4 +3260,12 @@ virNodeDeviceGetAPMatrixDynamicCaps(const char *sysf= sPath G_GNUC_UNUSED, return -1; } =20 +int +virNodeDeviceGetMdevParentDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, + virNodeDevCapMdevParent *mdev_parent= G_GNUC_UNUSED) +{ + return -1; +} + + #endif /* __linux__ */ diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index a234b4147b..21622c62ac 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -306,6 +306,14 @@ struct _virNodeDevCapAPMatrix { size_t nmdev_types; }; =20 + +typedef struct _virNodeDevCapMdevParent virNodeDevCapMdevParent; +struct _virNodeDevCapMdevParent { + virMediatedDeviceType **mdev_types; + size_t nmdev_types; + char *address; +}; + typedef struct _virNodeDevCapData virNodeDevCapData; struct _virNodeDevCapData { virNodeDevCapType type; @@ -327,6 +335,7 @@ struct _virNodeDevCapData { virNodeDevCapAPCard ap_card; virNodeDevCapAPQueue ap_queue; virNodeDevCapAPMatrix ap_matrix; + virNodeDevCapMdevParent mdev_parent; }; }; =20 @@ -453,6 +462,10 @@ int virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath, virNodeDevCapAPMatrix *ap_matrix); =20 +int +virNodeDeviceGetMdevParentDynamicCaps(const char *sysfsPath, + virNodeDevCapMdevParent *mdev_parent= ); + int virNodeDeviceUpdateCaps(virNodeDeviceDef *def); =20 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f4732f1742..1a5fce22e5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -866,6 +866,7 @@ virNodeDeviceDefParseNode; virNodeDeviceDefParseString; virNodeDeviceGetAPMatrixDynamicCaps; virNodeDeviceGetCSSDynamicCaps; +virNodeDeviceGetMdevParentDynamicCaps; virNodeDeviceGetPCIDynamicCaps; virNodeDeviceGetSCSIHostCaps; virNodeDeviceGetSCSITargetCaps; @@ -2723,6 +2724,7 @@ virMediatedDeviceListStealIndex; virMediatedDeviceModelTypeFromString; virMediatedDeviceModelTypeToString; virMediatedDeviceNew; +virMediatedDeviceParentGetAddress; virMediatedDeviceSetUsedBy; virMediatedDeviceTypeFree; virMediatedDeviceTypeReadAttrs; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de= vice_driver.c index 0178ae8b66..fa3cfcf24c 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -672,6 +672,10 @@ nodeDeviceObjFormatAddress(virNodeDeviceObj *obj) addr =3D g_strdup(caps->data.ap_matrix.addr); break; =20 + case VIR_NODE_DEV_CAP_MDEV_TYPES: + addr =3D g_strdup(caps->data.mdev_parent.address); + break; + case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_INTERFACE: @@ -684,7 +688,6 @@ nodeDeviceObjFormatAddress(virNodeDeviceObj *obj) case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_DRM: - case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_MDEV: case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_VDPA: diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index 3d69bdedae..e76c1a36b8 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -457,6 +457,28 @@ udevProcessPCI(struct udev_device *device, } =20 =20 +static int +udevProcessMdevParent(struct udev_device *device, + virNodeDeviceDef *def) +{ + virNodeDevCapMdevParent *mdev_parent =3D &def->caps->data.mdev_parent; + + udevGenerateDeviceName(device, def, NULL); + + if (virMediatedDeviceParentGetAddress(def->sysfs_path, &mdev_parent->a= ddress) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to find address for mdev parent device '%= s'"), + def->name); + return -1; + } + + if (virNodeDeviceGetMdevParentDynamicCaps(def->sysfs_path, mdev_parent= ) < 0) + return -1; + + return 0; +} + + static int drmGetMinorType(int minor) { @@ -1349,6 +1371,8 @@ udevGetDeviceType(struct udev_device *device, *type =3D VIR_NODE_DEV_CAP_VDPA; else if (STREQ_NULLABLE(subsystem, "matrix")) *type =3D VIR_NODE_DEV_CAP_AP_MATRIX; + else if (STREQ_NULLABLE(subsystem, "mtty")) + *type =3D VIR_NODE_DEV_CAP_MDEV_TYPES; =20 VIR_FREE(subsystem); } @@ -1404,6 +1428,7 @@ udevGetDeviceDetails(struct udev_device *device, case VIR_NODE_DEV_CAP_AP_MATRIX: return udevProcessAPMatrix(device, def); case VIR_NODE_DEV_CAP_MDEV_TYPES: + return udevProcessMdevParent(device, def); case VIR_NODE_DEV_CAP_VPD: case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_FC_HOST: diff --git a/src/util/virmdev.c b/src/util/virmdev.c index eb566982b1..41d4cef8b9 100644 --- a/src/util/virmdev.c +++ b/src/util/virmdev.c @@ -520,6 +520,34 @@ void virMediatedDeviceAttrFree(virMediatedDeviceAttr *= attr) } =20 =20 +#define MDEV_BUS_DIR "/sys/class/mdev_bus" + + +int +virMediatedDeviceParentGetAddress(const char *sysfspath, + char **address) +{ + g_autoptr(DIR) dir =3D NULL; + struct dirent *entry; + if (virDirOpen(&dir, MDEV_BUS_DIR) < 0) + return -1; + + /* check if one of the links in /sys/class/mdev_bus/ points at the sys= fs + * path for this device. If so, the link name is treated as the 'addre= ss' + * for the mdev parent */ + while (virDirRead(dir, &entry, MDEV_BUS_DIR) > 0) { + g_autofree char *tmppath =3D g_strdup_printf("%s/%s", MDEV_BUS_DIR, + entry->d_name); + + if (virFileLinkPointsTo(tmppath, sysfspath)) { + *address =3D g_strdup(entry->d_name); + return 0; + } + } + + return -1; +} + #ifdef __linux__ =20 ssize_t diff --git a/src/util/virmdev.h b/src/util/virmdev.h index 4d3655a091..bc8306d0e1 100644 --- a/src/util/virmdev.h +++ b/src/util/virmdev.h @@ -149,5 +149,9 @@ virMediatedDeviceGetMdevTypes(const char *sysfspath, virMediatedDeviceType ***types, size_t *ntypes); =20 +int +virMediatedDeviceParentGetAddress(const char *sysfspath, + char **address); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMediatedDevice, virMediatedDeviceFree); G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMediatedDeviceType, virMediatedDeviceType= Free); --=20 2.35.3