2017-03-23 19:01:41 +03:00
/*
2017-04-05 17:13:52 +03:00
* virnumamock . c : Mock some virNuma functions using sysfs
2017-03-23 19:01:41 +03: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 "internal.h"
# include "virmock.h"
# include "virnuma.h"
# include "virfile.h"
# include "viralloc.h"
# include "virstring.h"
# define VIR_FROM_THIS VIR_FROM_NONE
2017-04-05 17:13:52 +03:00
# define SYSFS_SYSTEM_PATH " / sys / devices / system"
2017-03-23 19:01:41 +03:00
static int numa_avail = - 1 ;
/*
* Poor man ' s mocked NUMA guesser . We basically check if
* / sys / devices / system / node ( where / sys / devices / system can already be mocked or
* changed in the tests ) exists and cache the result .
*/
bool
virNumaIsAvailable ( void )
{
if ( numa_avail < 0 ) {
char * sysfs_node_path = NULL ;
2017-04-05 17:13:52 +03:00
if ( virAsprintfQuiet ( & sysfs_node_path , " %s/node " , SYSFS_SYSTEM_PATH ) < 0 )
2017-03-23 19:01:41 +03:00
return false ;
numa_avail = virFileExists ( sysfs_node_path ) ;
VIR_FREE ( sysfs_node_path ) ;
}
/*
* Quite a few more things need to be mocked if NUMA is not available and
* you are using this file . Do not remove the abort ( ) call below unless you
* make sure all under virCapabilitiesInitNUMAFake ( ) is mocked ( and whatever
* might have changed since this comment was added . You are welcome .
*/
if ( ! numa_avail )
abort ( ) ;
return numa_avail ;
}
int
virNumaGetMaxNode ( void )
{
int ret = - 1 ;
virBitmapPtr map = NULL ;
2017-04-05 17:13:52 +03:00
if ( virFileReadValueBitmap ( & map , " %s/node/online " , SYSFS_SYSTEM_PATH ) < 0 )
2017-03-23 19:01:41 +03:00
return - 1 ;
ret = virBitmapLastSetBit ( map ) ;
virBitmapFree ( map ) ;
return ret ;
}
bool
virNumaNodeIsAvailable ( int node )
{
bool ret = false ;
virBitmapPtr map = NULL ;
2017-04-05 17:13:52 +03:00
if ( virFileReadValueBitmap ( & map , " %s/node/online " , SYSFS_SYSTEM_PATH ) < 0 )
2017-03-23 19:01:41 +03:00
return false ;
ret = virBitmapIsBitSet ( map , node ) ;
virBitmapFree ( map ) ;
return ret ;
}
int
virNumaGetNodeMemory ( int node ,
unsigned long long * memsize ,
unsigned long long * memfree )
{
const unsigned long long base = 1 < < 30 ;
if ( memsize )
* memsize = base * ( node + 1 ) ;
if ( memfree )
* memfree = base ;
return 0 ;
}
int
2019-10-14 15:45:03 +03:00
virNumaGetDistances ( int node G_GNUC_UNUSED ,
2017-03-23 19:01:41 +03:00
int * * distances ,
int * ndistances )
{
* distances = NULL ;
* ndistances = 0 ;
return 0 ;
}
/*
2017-04-05 17:13:52 +03:00
* TODO : Adapt virNumaGetHugePageInfo { Path , Dir } to use sysfs so that the
2017-03-23 19:01:41 +03:00
* paths can be modified and this function can be thrown away and instead we ' d
* have copied info from / sys ( as we do with / sys / devices / system ) .
*/
int
virNumaGetPages ( int node ,
unsigned int * * pages_size ,
2018-04-23 17:36:53 +03:00
unsigned long long * * pages_avail ,
unsigned long long * * pages_free ,
2017-03-23 19:01:41 +03:00
size_t * npages )
{
const int pages_def [ ] = { 4 , 2 * 1024 , 1 * 1024 * 1024 } ;
const int npages_def = ARRAY_CARDINALITY ( pages_def ) ;
size_t i = 0 ;
if ( pages_size )
* pages_size = NULL ;
if ( pages_avail )
* pages_avail = NULL ;
if ( pages_free )
* pages_free = NULL ;
* npages = 0 ;
if ( ( pages_size & & VIR_ALLOC_N ( * pages_size , npages_def ) < 0 ) | |
( pages_avail & & VIR_ALLOC_N ( * pages_avail , npages_def ) < 0 ) | |
( pages_free & & VIR_ALLOC_N ( * pages_free , npages_def ) < 0 ) ) {
VIR_FREE ( * pages_size ) ;
VIR_FREE ( * pages_avail ) ;
return - 1 ;
}
* npages = npages_def ;
if ( pages_size )
memcpy ( * pages_size , pages_def , sizeof ( pages_def ) ) ;
node + + ;
if ( node < = 0 )
node = 32 ;
if ( pages_avail | | pages_free ) {
for ( i = 0 ; i < * npages ; i + + ) {
if ( pages_avail )
( * pages_avail ) [ i ] = ( node + i ) * 2 < < 10 ;
if ( pages_free )
( * pages_free ) [ i ] = ( node + i ) * 1 < < 10 ;
}
}
return 0 ;
}
int
virNumaGetNodeCPUs ( int node , virBitmapPtr * cpus )
{
int ret = - 1 ;
char * cpulist = NULL ;
2017-04-05 17:13:52 +03:00
if ( virFileReadValueString ( & cpulist ,
" %s/node/node%u/cpulist " ,
SYSFS_SYSTEM_PATH , node ) < 0 )
2017-03-23 19:01:41 +03:00
return - 1 ;
* cpus = virBitmapParseUnlimited ( cpulist ) ;
2017-03-27 16:47:58 +03:00
if ( ! * cpus )
2017-03-23 19:01:41 +03:00
goto cleanup ;
ret = virBitmapCountBits ( * cpus ) ;
cleanup :
VIR_FREE ( cpulist ) ;
return ret ;
}