2014-03-06 12:08:36 +04:00
/*
* Copyright ( C ) 2014 SUSE LINUX Products GmbH , Nuernberg , Germany .
2016-04-06 16:46:49 +03:00
* Copyright ( C ) 2014 - 2016 Red Hat , Inc .
2014-03-06 12:08:36 +04:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
# include "testutils.h"
# ifdef __linux__
# include <sys / types.h>
# include <sys / stat.h>
# include <sys / ioctl.h>
# include <fcntl.h>
# include "virlog.h"
# include "virhostdev.h"
# define VIR_FROM_THIS VIR_FROM_NONE
2014-02-28 16:16:17 +04:00
VIR_LOG_INIT ( " tests.hostdevtest " ) ;
2019-06-14 15:30:13 +03:00
# define CHECK_LIST_COUNT(list, cnt, cb) \
2017-11-03 15:09:47 +03:00
do { \
size_t actualCount ; \
2019-06-14 15:30:13 +03:00
if ( ( actualCount = cb ( list ) ) ! = cnt ) { \
2017-11-03 15:09:47 +03:00
virReportError ( VIR_ERR_INTERNAL_ERROR , \
" Unexpected count of items in " # list " : %zu, " \
" expecting %zu " , actualCount , ( size_t ) cnt ) ; \
2019-08-27 17:00:55 +03:00
return - 1 ; \
2017-11-03 15:09:47 +03:00
} \
2016-03-02 17:23:51 +03:00
} while ( 0 )
2014-03-06 12:08:36 +04:00
2019-06-14 15:30:13 +03:00
# define CHECK_PCI_LIST_COUNT(list, cnt) \
CHECK_LIST_COUNT ( list , cnt , virPCIDeviceListCount )
2019-06-13 10:41:15 +03:00
# define CHECK_NVME_LIST_COUNT(list, cnt) \
CHECK_LIST_COUNT ( list , cnt , virNVMeDeviceListCount )
2014-03-06 12:08:36 +04:00
# define TEST_STATE_DIR abs_builddir " / hostdevmgr"
static const char * drv_name = " test_driver " ;
static const char * dom_name = " test_domain " ;
static const unsigned char * uuid =
( unsigned char * ) ( " f92360b0-2541-8791-fb32-d1f838811541 " ) ;
static int nhostdevs = 3 ;
2021-03-11 10:16:13 +03:00
static virDomainHostdevDef * hostdevs [ ] = { NULL , NULL , NULL } ;
static virPCIDevice * dev [ ] = { NULL , NULL , NULL } ;
static virHostdevManager * mgr ;
2019-06-13 10:41:15 +03:00
static const size_t ndisks = 3 ;
2021-03-11 10:16:13 +03:00
static virDomainDiskDef * disks [ ] = { NULL , NULL , NULL } ;
2019-06-13 10:41:15 +03:00
static const char * diskXML [ ] = {
" <disk type='nvme' device='disk'> "
" <driver name='qemu' type='raw'/> "
" <source type='pci' managed='yes' namespace='1'> "
" <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> "
" </source> "
" <target dev='vda' bus='virtio'/> "
" <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> "
" </disk> " ,
" <disk type='nvme' device='disk'> "
" <driver name='qemu' type='raw'/> "
" <source type='pci' managed='yes' namespace='2'> "
" <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> "
" </source> "
" <target dev='vdb' bus='virtio'/> "
" <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> "
" </disk> " ,
" <disk type='nvme' device='disk'> "
" <driver name='qemu' type='raw'/> "
" <source type='pci' managed='no' namespace='1'> "
" <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> "
" </source> "
" <target dev='vdc' bus='virtio'/> "
" <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> "
" </disk> "
} ;
2014-03-06 12:08:36 +04:00
static void
myCleanup ( void )
{
size_t i ;
for ( i = 0 ; i < nhostdevs ; i + + ) {
virPCIDeviceFree ( dev [ i ] ) ;
virDomainHostdevDefFree ( hostdevs [ i ] ) ;
}
2019-06-13 10:41:15 +03:00
for ( i = 0 ; i < ndisks ; i + + )
virDomainDiskDefFree ( disks [ i ] ) ;
2014-03-06 12:08:36 +04:00
if ( mgr ) {
2015-09-15 23:33:36 +03:00
if ( ! getenv ( " LIBVIRT_SKIP_CLEANUP " ) )
2014-04-28 17:34:52 +04:00
virFileDeleteTree ( mgr - > stateDir ) ;
2014-03-06 12:08:36 +04:00
virObjectUnref ( mgr - > activePCIHostdevs ) ;
virObjectUnref ( mgr - > activeUSBHostdevs ) ;
2017-08-10 10:14:36 +03:00
virObjectUnref ( mgr - > inactivePCIHostdevs ) ;
virObjectUnref ( mgr - > activeSCSIHostdevs ) ;
2019-06-13 10:41:15 +03:00
virObjectUnref ( mgr - > activeNVMeHostdevs ) ;
2014-03-06 12:08:36 +04:00
VIR_FREE ( mgr - > stateDir ) ;
VIR_FREE ( mgr ) ;
}
}
static int
myInit ( void )
{
size_t i ;
for ( i = 0 ; i < nhostdevs ; i + + ) {
2023-02-06 18:03:44 +03:00
virDomainHostdevSubsys * subsys ;
2017-09-23 14:03:50 +03:00
hostdevs [ i ] = virDomainHostdevDefNew ( ) ;
2014-03-06 12:08:36 +04:00
if ( ! hostdevs [ i ] )
goto cleanup ;
hostdevs [ i ] - > mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ;
2023-02-06 18:03:44 +03:00
subsys = & hostdevs [ i ] - > source . subsys ;
subsys - > type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI ;
subsys - > u . pci . addr . domain = 0 ;
subsys - > u . pci . addr . bus = 0 ;
subsys - > u . pci . addr . slot = i + 1 ;
subsys - > u . pci . addr . function = 0 ;
subsys - > u . pci . backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO ;
2014-03-06 12:08:36 +04:00
}
for ( i = 0 ; i < nhostdevs ; i + + ) {
2023-02-06 18:03:44 +03:00
virDomainHostdevSubsys * subsys = & hostdevs [ i ] - > source . subsys ;
if ( ! ( dev [ i ] = virPCIDeviceNew ( & subsys - > u . pci . addr ) ) )
2014-03-06 12:08:36 +04:00
goto cleanup ;
2015-10-23 12:54:07 +03:00
2019-08-12 18:25:57 +03:00
virPCIDeviceSetStubDriver ( dev [ i ] , VIR_PCI_STUB_DRIVER_VFIO ) ;
2014-03-06 12:08:36 +04:00
}
2019-06-13 10:41:15 +03:00
for ( i = 0 ; i < ndisks ; i + + ) {
if ( ! ( disks [ i ] = virDomainDiskDefParse ( diskXML [ i ] , NULL , 0 ) ) )
goto cleanup ;
}
2020-09-23 01:42:45 +03:00
mgr = g_new0 ( virHostdevManager , 1 ) ;
2014-03-06 12:08:36 +04:00
if ( ( mgr - > activePCIHostdevs = virPCIDeviceListNew ( ) ) = = NULL )
goto cleanup ;
if ( ( mgr - > activeUSBHostdevs = virUSBDeviceListNew ( ) ) = = NULL )
goto cleanup ;
if ( ( mgr - > inactivePCIHostdevs = virPCIDeviceListNew ( ) ) = = NULL )
goto cleanup ;
if ( ( mgr - > activeSCSIHostdevs = virSCSIDeviceListNew ( ) ) = = NULL )
goto cleanup ;
2019-06-13 10:41:15 +03:00
if ( ( mgr - > activeNVMeHostdevs = virNVMeDeviceListNew ( ) ) = = NULL )
goto cleanup ;
2019-10-20 14:49:46 +03:00
mgr - > stateDir = g_strdup ( TEST_STATE_DIR ) ;
2021-02-26 11:37:10 +03:00
if ( g_mkdir_with_parents ( mgr - > stateDir , 0777 ) < 0 )
2014-03-06 12:08:36 +04:00
goto cleanup ;
return 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2014-03-06 12:08:36 +04:00
myCleanup ( ) ;
return - 1 ;
}
static int
2016-03-03 18:13:04 +03:00
testVirHostdevPreparePCIHostdevs_unmanaged ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:27:06 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + )
hostdevs [ i ] - > managed = false ;
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
/* Test normal functionality */
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test 0 hostdevs " ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , dom_name , uuid ,
NULL , 0 , 0 ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
/* Test unmanaged hostdevs */
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test >=1 unmanaged hostdevs " ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , dom_name , uuid ,
hostdevs , nhostdevs , 0 ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count + nhostdevs ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count - nhostdevs ) ;
2014-03-06 12:08:36 +04:00
/* Test conflict */
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for same driver/domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , dom_name , uuid ,
& hostdevs [ 0 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for same driver, diff domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , " test_domain1 " , uuid ,
& hostdevs [ 1 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for diff driver/domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , " test_driver1 " , dom_name , uuid ,
& hostdevs [ 2 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-03 18:13:04 +03:00
testVirHostdevReAttachPCIHostdevs_unmanaged ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:27:06 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + ) {
if ( hostdevs [ i ] - > managed ! = false ) {
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " invalid test " ) ;
2014-03-06 12:08:36 +04:00
return - 1 ;
}
}
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test 0 hostdevs " ) ;
2021-01-26 08:31:16 +03:00
virHostdevReAttachPCIDevices ( mgr , drv_name , dom_name , NULL , 0 ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test >=1 unmanaged hostdevs " ) ;
2014-03-06 12:08:36 +04:00
virHostdevReAttachPCIDevices ( mgr , drv_name , dom_name ,
2021-01-26 08:31:16 +03:00
hostdevs , nhostdevs ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count - nhostdevs ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count + nhostdevs ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-18 20:03:53 +03:00
testVirHostdevPreparePCIHostdevs_managed ( bool mixed )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + )
hostdevs [ i ] - > managed = true ;
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:33:18 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
/* Test normal functionality */
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test >=1 hostdevs " ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , dom_name , uuid ,
hostdevs , nhostdevs , 0 ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count + nhostdevs ) ;
2016-03-18 20:03:53 +03:00
/* If testing a mixed roundtrip, devices are already in the inactive list
* before we start and are removed from it as soon as we attach them to
* the guest */
if ( mixed )
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count - nhostdevs ) ;
2016-03-18 20:03:53 +03:00
else
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
/* Test conflict */
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:33:18 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for same driver/domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , dom_name , uuid ,
& hostdevs [ 0 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for same driver, diff domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , drv_name , " test_domain1 " , uuid ,
& hostdevs [ 1 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test: prepare same hostdevs for diff driver/domain again " ) ;
2019-08-27 17:00:10 +03:00
if ( virHostdevPreparePCIDevices ( mgr , " test_driver1 " , dom_name , uuid ,
& hostdevs [ 2 ] , 1 , 0 ) = = 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-08-27 17:08:12 +03:00
virResetLastError ( ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-18 20:03:53 +03:00
testVirHostdevReAttachPCIHostdevs_managed ( bool mixed )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + ) {
if ( hostdevs [ i ] - > managed ! = true ) {
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " invalid test " ) ;
2014-03-06 12:08:36 +04:00
return - 1 ;
}
}
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:33:18 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test 0 hostdevs " ) ;
2021-01-26 08:31:16 +03:00
virHostdevReAttachPCIDevices ( mgr , drv_name , dom_name , NULL , 0 ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test >=1 hostdevs " ) ;
2014-03-06 12:08:36 +04:00
virHostdevReAttachPCIDevices ( mgr , drv_name , dom_name ,
2021-01-26 08:31:16 +03:00
hostdevs , nhostdevs ) ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count - nhostdevs ) ;
2016-03-18 20:03:53 +03:00
/* If testing a mixed roundtrip, devices are added back to the inactive
* list as soon as we detach from the guest */
if ( mixed )
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count + nhostdevs ) ;
2016-03-18 20:03:53 +03:00
else
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-03 18:13:04 +03:00
testVirHostdevDetachPCINodeDevice ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + ) {
2016-03-02 17:33:18 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:15:07 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPCINodeDeviceDetach ( mgr , dev [ i ] ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count + 1 ) ;
2014-03-06 12:08:36 +04:00
}
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
2016-03-03 18:13:04 +03:00
2014-03-06 12:08:36 +04:00
static int
2016-03-03 18:13:04 +03:00
testVirHostdevResetPCINodeDevice ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + ) {
2016-03-02 17:33:18 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPCINodeDeviceReset ( mgr , dev [ i ] ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
}
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-03 18:13:04 +03:00
testVirHostdevReAttachPCINodeDevice ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count , i ;
2014-03-06 12:08:36 +04:00
for ( i = 0 ; i < nhostdevs ; i + + ) {
2016-03-02 17:33:18 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:15:07 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevPCINodeDeviceReAttach ( mgr , dev [ i ] ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count - 1 ) ;
2014-03-06 12:08:36 +04:00
}
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
static int
2016-03-03 18:13:04 +03:00
testVirHostdevUpdateActivePCIHostdevs ( void )
2014-03-06 12:08:36 +04:00
{
2016-03-02 17:33:18 +03:00
size_t active_count , inactive_count ;
2014-03-06 12:08:36 +04:00
2016-03-02 17:15:07 +03:00
active_count = virPCIDeviceListCount ( mgr - > activePCIHostdevs ) ;
2016-03-02 17:33:18 +03:00
inactive_count = virPCIDeviceListCount ( mgr - > inactivePCIHostdevs ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test 0 hostdevs " ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevUpdateActivePCIDevices ( mgr , NULL , 0 ,
drv_name , dom_name ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:07:36 +03:00
VIR_TEST_DEBUG ( " Test >=1 hostdevs " ) ;
2014-03-06 12:08:36 +04:00
if ( virHostdevUpdateActivePCIDevices ( mgr , hostdevs , nhostdevs ,
drv_name , dom_name ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-06-14 15:30:13 +03:00
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , active_count + nhostdevs ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , inactive_count ) ;
2014-03-06 12:08:36 +04:00
2019-08-27 17:00:55 +03:00
return 0 ;
2014-03-06 12:08:36 +04:00
}
2016-03-18 20:03:53 +03:00
/**
* testVirHostdevRoundtripNoGuest :
* @ opaque : unused
*
* Perform a roundtrip without ever assigning devices to the guest .
*
* 1. Detach devices from the host
* 2. Reattach devices to the host
*/
static int
2019-10-14 15:45:03 +03:00
testVirHostdevRoundtripNoGuest ( const void * opaque G_GNUC_UNUSED )
2016-03-18 20:03:53 +03:00
{
if ( testVirHostdevDetachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-18 20:03:53 +03:00
if ( testVirHostdevReAttachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-18 20:03:53 +03:00
2019-08-27 17:00:55 +03:00
return 0 ;
2016-03-18 20:03:53 +03:00
}
2016-03-03 18:13:04 +03:00
/**
* testVirHostdevRoundtripUnmanaged :
* @ opaque : unused
*
* Perform a roundtrip with unmanaged devices .
*
* 1. Detach devices from the host
* 2. Attach devices to the guest as unmanaged
* 3. Detach devices from the guest as unmanaged
* 4. Reattach devices to the host
*/
static int
2019-10-14 15:45:03 +03:00
testVirHostdevRoundtripUnmanaged ( const void * opaque G_GNUC_UNUSED )
2016-03-03 18:13:04 +03:00
{
if ( testVirHostdevDetachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-05-02 15:51:52 +03:00
if ( testVirHostdevPreparePCIHostdevs_unmanaged ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-05-02 15:51:52 +03:00
if ( testVirHostdevReAttachPCIHostdevs_unmanaged ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-03 18:13:04 +03:00
if ( testVirHostdevReAttachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-03 18:13:04 +03:00
2019-08-27 17:00:55 +03:00
return 0 ;
2016-03-03 18:13:04 +03:00
}
/**
* testVirHostdevRoundtripManaged :
* @ opaque : unused
*
* Perform a roundtrip with managed devices .
*
* 1. Attach devices to the guest as managed
* 2. Detach devices from the guest as managed
*/
static int
2019-10-14 15:45:03 +03:00
testVirHostdevRoundtripManaged ( const void * opaque G_GNUC_UNUSED )
2016-03-03 18:13:04 +03:00
{
2019-05-02 15:51:52 +03:00
if ( testVirHostdevPreparePCIHostdevs_managed ( false ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-05-02 15:51:52 +03:00
if ( testVirHostdevReAttachPCIHostdevs_managed ( false ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-03 18:13:04 +03:00
2019-08-27 17:00:55 +03:00
return 0 ;
2016-03-03 18:13:04 +03:00
}
2016-03-18 20:03:53 +03:00
/**
* testVirHostdevRoundtripMixed :
* @ opaque : unused
*
* Perform a roundtrip with managed devices but manually detach the devices
* from the host first .
*
* 1. Detach devices from the host
* 2. Attach devices to the guest as managed
* 3. Detach devices from the guest as managed
* 4. Reattach devices to the host
*/
static int
2019-10-14 15:45:03 +03:00
testVirHostdevRoundtripMixed ( const void * opaque G_GNUC_UNUSED )
2016-03-18 20:03:53 +03:00
{
if ( testVirHostdevDetachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-05-02 15:51:52 +03:00
if ( testVirHostdevPreparePCIHostdevs_managed ( true ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2019-05-02 15:51:52 +03:00
if ( testVirHostdevReAttachPCIHostdevs_managed ( true ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-18 20:03:53 +03:00
if ( testVirHostdevReAttachPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-18 20:03:53 +03:00
2019-08-27 17:00:55 +03:00
return 0 ;
2016-03-18 20:03:53 +03:00
}
2016-03-03 18:13:04 +03:00
/**
* testVirHostdevOther :
* @ opaque : unused
*
* Perform other operations on devices .
*
* 1. Reset devices
* 2. Update list of active devices
*/
static int
2019-10-14 15:45:03 +03:00
testVirHostdevOther ( const void * opaque G_GNUC_UNUSED )
2016-03-03 18:13:04 +03:00
{
if ( testVirHostdevResetPCINodeDevice ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-03 18:13:04 +03:00
if ( testVirHostdevUpdateActivePCIHostdevs ( ) < 0 )
2019-08-27 17:00:55 +03:00
return - 1 ;
2016-03-03 18:13:04 +03:00
2019-08-27 17:00:55 +03:00
return 0 ;
2016-03-03 18:13:04 +03:00
}
2019-06-13 10:41:15 +03:00
static int
testNVMeDiskRoundtrip ( const void * opaque G_GNUC_UNUSED )
{
/* Don't rely on a state that previous test cases might have
* left the manager in . Start with a clean slate . */
virHostdevReAttachPCIDevices ( mgr , drv_name , dom_name ,
2021-01-26 08:31:16 +03:00
hostdevs , nhostdevs ) ;
2019-06-13 10:41:15 +03:00
CHECK_NVME_LIST_COUNT ( mgr - > activeNVMeHostdevs , 0 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , 0 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , 0 ) ;
/* Firstly, attach all NVMe disks */
if ( virHostdevPrepareNVMeDevices ( mgr , drv_name , dom_name , disks , ndisks ) < 0 )
2020-01-07 00:57:49 +03:00
return - 1 ;
2019-06-13 10:41:15 +03:00
CHECK_NVME_LIST_COUNT ( mgr - > activeNVMeHostdevs , 3 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , 2 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , 0 ) ;
/* Now, try to detach the first one. */
if ( virHostdevReAttachNVMeDevices ( mgr , drv_name , dom_name , disks , 1 ) < 0 )
2020-01-07 00:57:49 +03:00
return - 1 ;
2019-06-13 10:41:15 +03:00
CHECK_NVME_LIST_COUNT ( mgr - > activeNVMeHostdevs , 2 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , 2 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , 0 ) ;
/* And the last one */
if ( virHostdevReAttachNVMeDevices ( mgr , drv_name , dom_name , & disks [ 2 ] , 1 ) < 0 )
2020-01-07 00:57:49 +03:00
return - 1 ;
2019-06-13 10:41:15 +03:00
CHECK_NVME_LIST_COUNT ( mgr - > activeNVMeHostdevs , 1 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , 1 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , 0 ) ;
/* Finally, detach the middle one */
if ( virHostdevReAttachNVMeDevices ( mgr , drv_name , dom_name , & disks [ 1 ] , 1 ) < 0 )
2020-01-07 00:57:49 +03:00
return - 1 ;
2019-06-13 10:41:15 +03:00
CHECK_NVME_LIST_COUNT ( mgr - > activeNVMeHostdevs , 0 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > activePCIHostdevs , 0 ) ;
CHECK_PCI_LIST_COUNT ( mgr - > inactivePCIHostdevs , 0 ) ;
2020-01-07 00:57:49 +03:00
return 0 ;
2019-06-13 10:41:15 +03:00
}
2015-12-04 15:38:16 +03:00
# define FAKEROOTDIRTEMPLATE abs_builddir " / fakerootdir-XXXXXX"
2014-03-06 12:08:36 +04:00
static int
mymain ( void )
{
int ret = 0 ;
2019-10-15 16:16:31 +03:00
g_autofree char * fakerootdir = NULL ;
2014-03-06 12:08:36 +04:00
2019-10-20 14:49:46 +03:00
fakerootdir = g_strdup ( FAKEROOTDIRTEMPLATE ) ;
2014-03-06 12:08:36 +04:00
2019-11-14 00:35:47 +03:00
if ( ! g_mkdtemp ( fakerootdir ) ) {
2015-12-04 15:38:16 +03:00
fprintf ( stderr , " Cannot create fakerootdir " ) ;
2014-03-06 12:08:36 +04:00
abort ( ) ;
}
2019-12-18 20:16:19 +03:00
g_setenv ( " LIBVIRT_FAKE_ROOT_DIR " , fakerootdir , TRUE ) ;
2014-03-06 12:08:36 +04:00
2017-11-03 15:09:47 +03:00
# define DO_TEST(fnc) \
do { \
if ( virTestRun ( # fnc , fnc , NULL ) < 0 ) \
ret = - 1 ; \
2014-03-06 12:08:36 +04:00
} while ( 0 )
2019-06-14 11:39:24 +03:00
if ( myInit ( ) < 0 ) {
2014-03-06 12:08:36 +04:00
fprintf ( stderr , " Init data structures failed. " ) ;
2019-06-14 11:39:24 +03:00
virFileDeleteTree ( fakerootdir ) ;
return EXIT_FAILURE ;
}
2014-03-06 12:08:36 +04:00
2016-03-18 20:03:53 +03:00
DO_TEST ( testVirHostdevRoundtripNoGuest ) ;
2016-03-03 18:13:04 +03:00
DO_TEST ( testVirHostdevRoundtripUnmanaged ) ;
DO_TEST ( testVirHostdevRoundtripManaged ) ;
2016-03-18 20:03:53 +03:00
DO_TEST ( testVirHostdevRoundtripMixed ) ;
2016-03-03 18:13:04 +03:00
DO_TEST ( testVirHostdevOther ) ;
2019-06-13 10:41:15 +03:00
DO_TEST ( testNVMeDiskRoundtrip ) ;
2014-03-06 12:08:36 +04:00
myCleanup ( ) ;
if ( getenv ( " LIBVIRT_SKIP_CLEANUP " ) = = NULL )
2015-12-04 15:38:16 +03:00
virFileDeleteTree ( fakerootdir ) ;
2014-03-06 12:08:36 +04:00
2014-03-17 13:38:38 +04:00
return ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ;
2014-03-06 12:08:36 +04:00
}
2020-05-06 15:38:42 +03:00
VIR_TEST_MAIN_PRELOAD ( mymain ,
VIR_TEST_MOCK ( " virhostdev " ) ,
VIR_TEST_MOCK ( " virpci " ) )
2014-03-06 12:08:36 +04:00
# else
int
main ( void )
{
return EXIT_AM_SKIP ;
}
# endif