2014-06-10 19:09:20 +04:00
/*
* Copyright ( C ) 2014 Red Hat , Inc .
*
* 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 <fcntl.h>
# include <sys / stat.h>
# include "virstring.h"
# include "virerror.h"
# include "virlog.h"
2017-01-23 22:48:12 +03:00
# include "virscsihost.h"
2014-06-10 19:09:20 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
VIR_LOG_INIT ( " tests.scsihosttest " ) ;
char * scsihost_class_path ;
# define TEST_SCSIHOST_CLASS_PATH scsihost_class_path
/*
* Initialized / create a mock sysfs environment with 4 scsi_host devices
* located on " 0000:00:1f.1 " and " 0000:00:1f.2 " . Each directory will
* contain 4 unique_id files having the same value .
*
* The environment is :
*
* 4 files :
*
* sys / devices / pci0000 : 00 / 0000 : 00 : 1f .1 / ata1 / host0 / scsi_host / host0 / unique_id
* sys / devices / pci0000 : 00 / 0000 : 00 : 1f .1 / ata2 / host1 / scsi_host / host1 / unique_id
* sys / devices / pci0000 : 00 / 0000 : 00 : 1f .2 / ata1 / host0 / scsi_host / host0 / unique_id
* sys / devices / pci0000 : 00 / 0000 : 00 : 1f .2 / ata2 / host1 / scsi_host / host1 / unique_id
*
* 4 symlinks :
*
* sys / class / scsi_host / host0 - > link to 1f .1 host 0
* sys / class / scsi_host / host1 - > link to 1f .1 host 1
* sys / class / scsi_host / host2 - > link to 1f .2 host 0
* sys / class / scsi_host / host3 - > link to 1f .2 host 1
*
* The unique_id ' s for host0 and host2 are set to " 1 "
* The unique_id ' s for host1 and host3 are set to " 2 "
*/
static int
create_scsihost ( const char * fakesysfsdir , const char * devicepath ,
const char * unique_id , const char * hostname )
{
char * unique_id_path = NULL ;
char * link_path = NULL ;
char * spot ;
int ret = - 1 ;
int fd = - 1 ;
2019-10-22 16:26:14 +03:00
unique_id_path = g_strdup_printf ( " %s/devices/pci0000:00/%s/unique_id " ,
fakesysfsdir , devicepath ) ;
link_path = g_strdup_printf ( " %s/class/scsi_host/%s " ,
fakesysfsdir , hostname ) ;
2014-06-10 19:09:20 +04:00
/* Rather than create path & file, temporarily snip off the file to
* create the path
*/
if ( ! ( spot = strstr ( unique_id_path , " unique_id " ) ) ) {
fprintf ( stderr , " Did not find unique_id in path \n " ) ;
goto cleanup ;
}
spot - - ;
* spot = ' \0 ' ;
if ( virFileMakePathWithMode ( unique_id_path , 0755 ) < 0 ) {
fprintf ( stderr , " Unable to make path to '%s' \n " , unique_id_path ) ;
goto cleanup ;
}
* spot = ' / ' ;
/* Rather than create path & file, temporarily snip off the file to
* create the path
*/
if ( ! ( spot = strstr ( link_path , hostname ) ) ) {
fprintf ( stderr , " Did not find hostname in path \n " ) ;
goto cleanup ;
}
spot - - ;
* spot = ' \0 ' ;
if ( virFileMakePathWithMode ( link_path , 0755 ) < 0 ) {
fprintf ( stderr , " Unable to make path to '%s' \n " , link_path ) ;
goto cleanup ;
}
* spot = ' / ' ;
if ( ( fd = open ( unique_id_path , O_CREAT | O_WRONLY , 0444 ) ) < 0 ) {
fprintf ( stderr , " Unable to create '%s' \n " , unique_id_path ) ;
goto cleanup ;
}
if ( safewrite ( fd , unique_id , 1 ) ! = 1 ) {
fprintf ( stderr , " Unable to write '%s' \n " , unique_id ) ;
goto cleanup ;
}
VIR_DEBUG ( " Created unique_id '%s' " , unique_id_path ) ;
/* The link is to the path not the file - so remove the file */
if ( ! ( spot = strstr ( unique_id_path , " unique_id " ) ) ) {
fprintf ( stderr , " Did not find unique_id in path \n " ) ;
goto cleanup ;
}
spot - - ;
* spot = ' \0 ' ;
if ( symlink ( unique_id_path , link_path ) < 0 ) {
fprintf ( stderr , " Unable to create symlink '%s' to '%s' \n " ,
link_path , unique_id_path ) ;
goto cleanup ;
}
VIR_DEBUG ( " Created symlink '%s' " , link_path ) ;
ret = 0 ;
cleanup :
VIR_FORCE_CLOSE ( fd ) ;
VIR_FREE ( unique_id_path ) ;
VIR_FREE ( link_path ) ;
return ret ;
}
static int
init_scsihost_sysfs ( const char * fakesysfsdir )
{
int ret = 0 ;
if ( create_scsihost ( fakesysfsdir ,
" 0000:00:1f.1/ata1/host0/scsi_host/host0 " ,
" 1 " , " host0 " ) < 0 | |
create_scsihost ( fakesysfsdir ,
" 0000:00:1f.1/ata2/host1/scsi_host/host1 " ,
" 2 " , " host1 " ) < 0 | |
create_scsihost ( fakesysfsdir ,
" 0000:00:1f.2/ata1/host0/scsi_host/host0 " ,
" 1 " , " host2 " ) < 0 | |
create_scsihost ( fakesysfsdir ,
" 0000:00:1f.2/ata2/host1/scsi_host/host1 " ,
" 2 " , " host3 " ) < 0 )
ret = - 1 ;
return ret ;
}
/* Test virReadSCSIUniqueId */
static int
2019-10-14 15:45:03 +03:00
testVirReadSCSIUniqueId ( const void * data G_GNUC_UNUSED )
2014-06-10 19:09:20 +04:00
{
int hostnum , unique_id ;
for ( hostnum = 0 ; hostnum < 4 ; hostnum + + ) {
2017-01-23 22:48:12 +03:00
if ( ( unique_id = virSCSIHostGetUniqueId ( TEST_SCSIHOST_CLASS_PATH ,
hostnum ) ) < 0 ) {
2014-06-10 19:09:20 +04:00
fprintf ( stderr , " Failed to read hostnum=%d unique_id \n " , hostnum ) ;
return - 1 ;
}
/* host0 and host2 have unique_id == 1
* host1 and host3 have unique_id = = 2
*/
if ( ( hostnum = = 0 | | hostnum = = 2 ) & & unique_id ! = 1 ) {
fprintf ( stderr , " The unique_id='%d' for hostnum=%d is wrong \n " ,
unique_id , hostnum ) ;
return - 1 ;
} else if ( ( hostnum = = 1 | | hostnum = = 3 ) & & unique_id ! = 2 ) {
fprintf ( stderr , " The unique_id='%d' for hostnum=%d is wrong \n " ,
unique_id , hostnum ) ;
return - 1 ;
}
}
return 0 ;
}
2017-01-23 22:48:12 +03:00
/* Test virSCSIHostFindByPCI */
2014-06-10 15:47:12 +04:00
static int
2019-10-14 15:45:03 +03:00
testVirFindSCSIHostByPCI ( const void * data G_GNUC_UNUSED )
2014-06-10 15:47:12 +04:00
{
unsigned int unique_id1 = 1 ;
unsigned int unique_id2 = 2 ;
const char * pci_addr1 = " 0000:00:1f.1 " ;
const char * pci_addr2 = " 0000:00:1f.2 " ;
char * path_addr = NULL ;
char * ret_host = NULL ;
int ret = - 1 ;
2019-10-22 16:26:14 +03:00
path_addr = g_strdup_printf ( " %s/%s " , abs_srcdir , " sysfs/class/scsi_host " ) ;
2014-06-10 15:47:12 +04:00
2017-01-23 22:48:12 +03:00
if ( ! ( ret_host = virSCSIHostFindByPCI ( TEST_SCSIHOST_CLASS_PATH ,
2014-06-10 15:47:12 +04:00
pci_addr1 , unique_id1 ) ) | |
STRNEQ ( ret_host , " host0 " ) )
goto cleanup ;
VIR_FREE ( ret_host ) ;
2017-01-23 22:48:12 +03:00
if ( ! ( ret_host = virSCSIHostFindByPCI ( TEST_SCSIHOST_CLASS_PATH ,
2014-06-10 15:47:12 +04:00
pci_addr1 , unique_id2 ) ) | |
STRNEQ ( ret_host , " host1 " ) )
goto cleanup ;
VIR_FREE ( ret_host ) ;
2017-01-23 22:48:12 +03:00
if ( ! ( ret_host = virSCSIHostFindByPCI ( TEST_SCSIHOST_CLASS_PATH ,
2014-06-10 15:47:12 +04:00
pci_addr2 , unique_id1 ) ) | |
STRNEQ ( ret_host , " host2 " ) )
goto cleanup ;
VIR_FREE ( ret_host ) ;
2017-01-23 22:48:12 +03:00
if ( ! ( ret_host = virSCSIHostFindByPCI ( TEST_SCSIHOST_CLASS_PATH ,
2014-06-10 15:47:12 +04:00
pci_addr2 , unique_id2 ) ) | |
STRNEQ ( ret_host , " host3 " ) )
goto cleanup ;
VIR_FREE ( ret_host ) ;
ret = 0 ;
cleanup :
VIR_FREE ( ret_host ) ;
VIR_FREE ( path_addr ) ;
return ret ;
}
2015-12-04 16:12:33 +03:00
# define FAKEROOTDIRTEMPLATE abs_builddir " / fakerootdir-XXXXXX"
2014-06-10 19:09:20 +04:00
static int
mymain ( void )
{
int ret = - 1 ;
2015-12-04 16:12:33 +03:00
char * fakerootdir = NULL ;
2014-06-10 19:09:20 +04:00
char * fakesysfsdir = NULL ;
2019-10-20 14:49:46 +03:00
fakerootdir = g_strdup ( FAKEROOTDIRTEMPLATE ) ;
2014-06-10 19:09:20 +04:00
2019-11-14 00:35:47 +03:00
if ( ! g_mkdtemp ( fakerootdir ) ) {
2015-12-04 16:12:33 +03:00
fprintf ( stderr , " Cannot create fakerootdir " ) ;
goto cleanup ;
}
2019-10-22 16:26:14 +03:00
fakesysfsdir = g_strdup_printf ( " %s/sys " , fakerootdir ) ;
2014-06-10 19:09:20 +04:00
if ( init_scsihost_sysfs ( fakesysfsdir ) < 0 ) {
fprintf ( stderr , " Failed to create fakesysfs='%s' \n " , fakesysfsdir ) ;
goto cleanup ;
}
2019-10-22 16:26:14 +03:00
scsihost_class_path = g_strdup_printf ( " %s/class/scsi_host " , fakesysfsdir ) ;
2014-06-10 19:09:20 +04:00
VIR_DEBUG ( " Reading from '%s' " , scsihost_class_path ) ;
2016-05-26 18:01:50 +03:00
if ( virTestRun ( " testVirReadSCSIUniqueId " ,
testVirReadSCSIUniqueId , NULL ) < 0 ) {
2014-06-10 19:09:20 +04:00
ret = - 1 ;
goto cleanup ;
}
2016-05-26 18:01:50 +03:00
if ( virTestRun ( " testVirFindSCSIHostByPCI " ,
testVirFindSCSIHostByPCI , NULL ) < 0 ) {
2014-06-10 15:47:12 +04:00
ret = - 1 ;
goto cleanup ;
}
2014-06-10 19:09:20 +04:00
ret = 0 ;
cleanup :
if ( getenv ( " LIBVIRT_SKIP_CLEANUP " ) = = NULL )
2015-12-04 16:12:33 +03:00
virFileDeleteTree ( fakerootdir ) ;
VIR_FREE ( fakerootdir ) ;
2014-06-10 19:09:20 +04:00
VIR_FREE ( fakesysfsdir ) ;
VIR_FREE ( scsihost_class_path ) ;
return ret ;
}
2017-03-29 17:45:42 +03:00
VIR_TEST_MAIN ( mymain )
2014-06-10 19:09:20 +04:00
# else
int
main ( void )
{
return EXIT_AM_SKIP ;
}
# endif