1#!/bin/sh 2#-*-sh-*- 3 4# 5# Copyright © 2009 CNRS 6# Copyright © 2009-2021 Inria. All rights reserved. 7# Copyright © 2009-2012 Université Bordeaux 8# Copyright © 2014 Cisco Systems, Inc. All rights reserved. 9# See COPYING in top-level directory. 10# 11 12HWLOC_VERSION="@HWLOC_VERSION@" 13HWLOC_top_builddir="@HWLOC_top_builddir@" 14prefix="@prefix@" 15exec_prefix="@exec_prefix@" 16bindir="@bindir@" 17localstatedir="@localstatedir@" 18runstatedir="@HWLOC_runstatedir@" 19# this will be changed into $bindir/lstopo during make install 20lstopo="$HWLOC_top_builddir/utils/lstopo/lstopo-no-graphics" 21hgcpuid="$HWLOC_top_builddir/utils/hwloc/hwloc-gather-cpuid" 22 23# make sure we use default numeric formats 24LANG=C 25LC_ALL=C 26export LANG LC_ALL 27 28# don't let ls append special chars after symlinks etc 29unalias -a ls 30 31gathercpuid=1 32gatherio=0 33gatherdmi=0 34keep=0 35 36if [ ! -x "$lstopo" ] 37then 38 error "Could not find lstopo executable in the install or build dir." 39 exit 1 40fi 41 42error() 43{ 44 echo $@ 2>&1 45} 46 47usage() 48{ 49 echo `basename $0`" [options] <savepath>" 50 echo " Saves the Linux topology files (/sys, /proc, ...) under <savepath>.tar.bz2" 51 echo " and the corresponding lstopo verbose output under <savepath>.output" 52 echo "Options:" 53 echo " --io Gather I/O files (takes much longer and generates much larger tarball)" 54 echo " --dmi Gather SMBIOS files. Works only when run as root. Requires dmi-sysfs kernel module" 55 echo " --no-cpuid Do not gather x86 CPUID using hwloc-gather-cpuid" 56 echo " --keep Keep the temporary copy of dumped files" 57 echo " --version Report version and exit" 58 echo " -h --help Show this usage" 59 echo "Example:" 60 echo " $0 /tmp/\$(uname -n)" 61} 62 63while [ x`echo "$1" | cut -c1` = x- ] ; do 64 case $1 in 65 --io) gatherio=1;; 66 --dmi) gatherdmi=1;; 67 --no-cpuid) gathercpuid=0;; 68 --keep) keep=1;; 69 --version) echo `basename $0`" $HWLOC_VERSION"; exit 0;; 70 -h|--help) usage; exit 0;; 71 *) echo "Unrecognized option: $1"; usage; exit 1;; 72 esac 73 shift 74done 75 76if test $# -lt 1 -o x$1 = x; then 77 usage 78 exit 1 79fi 80name="$1" 81basename=`basename "$name"` 82dirname=`dirname "$name"` 83 84if [ x$gatherio = x0 ]; then 85 echo "I/O files won't be saved (--io not given)." 86fi 87if [ x$gatherdmi = x0 ]; then 88 echo "DMI files won't be saved (--dmi not given)." 89fi 90 91echo 92echo "*** Note that this tool may be slow on large nodes or when I/O is enabled. ***" 93echo 94 95if ! mkdir -p "$dirname" ; then 96 error "Failed to create directory $dirname." 97 exit 1 98fi 99 100if [ ! -w "$dirname" ] ; then 101 echo "$dirname is not writable." 102 exit 1 103fi 104 105destdir=`mktemp -d --tmpdir hwloc-gather-topology.XXXXXXXX` 106 107# Use cat so that we properly get proc/sys files even if their 108# file length is wrong 109_savefile() { 110 local dest="$1" 111 local file="$2" 112 if test -r "$file"; then 113 dir=`dirname "$file"` 114 mkdir -p "$dest/$dir" 2>/dev/null 115 cat "$file" > "$dest/$file" 2>/dev/null 116 fi 117} 118 119_savelink() { 120 local dest="$1" 121 local file="$2" 122 dir=`dirname "$file"` 123 mkdir -p "$dest/$dir" 2>/dev/null 124 cp -P "$file" "$dest/$file" 125} 126 127# Get a file 128savefile() { 129 local dest="$1" 130 local file="$2" 131 echo " file $file" 132 _savefile "$dest" "$file" 133} 134 135# Get all files from the given directory 136# Ignore errors since some files may be missing, and some may be 137# restricted to root (but we don't need them). 138savedir() { 139 local dest="$1" 140 local path="$2" 141 echo " directory $path" 142 # gather all directories, including empty ones 143 find "$path" -type d 2>/dev/null | while read -r dir ; do 144 mkdir -p "$dest/$dir" 2>/dev/null 145 done 146 # gather all files now 147 find "$path" -type f 2>/dev/null | while read -r file ; do 148 test -e "$dest/$file" || _savefile "$dest" "$file" 149 done 150 # gather symlinks 151 find "$path" -type l 2>/dev/null | while read -r link ; do 152 test -e "$dest/$link" || _savelink "$dest" "$link" 153 done 154} 155 156# Save a class directory, including symlink targets (except in /devices/pci) and their device symlinks if any 157saveclassdir() { 158 local dest="$1" 159 local classname="$2" 160 161 test -d /sys/class/$classname/ || return 162 163 savedir "$dest" /sys/class/$classname/ 164 165 for dev in $(ls /sys/class/$classname/); do 166 target=$(readlink /sys/class/$classname/$dev 2>/dev/null | grep -v /devices/pci) 167 if test "x$target" != x; then 168 savedir "$dest" "/sys/class/$classname/$target" 169 fi 170 device=$(readlink /sys/class/$classname/$target/device 2>/dev/null | grep -v /devices/pci) 171 if test "x$device" != x; then 172 savedir "$dest" "/sys/class/$classname/$target/$device" 173 fi 174 done 175} 176 177# Save a bus devices directory, include symlinks target (except in /devices/pci) with a possible relative path, and their device symlink if any 178savebusdir() { 179 local dest="$1" 180 local busname="$2" 181 local relpath="$3" 182 183 test -d /sys/bus/$busname/devices/ || return 184 185 savedir "$dest" /sys/bus/$busname/devices/ 186 187 for dev in $(ls /sys/bus/$busname/devices/); do 188 target=$(readlink /sys/bus/$busname/devices/$dev 2>/dev/null | grep -v /devices/pci) 189 if test "x$target" != x; then 190 savedir "$dest" "/sys/bus/$busname/devices/$target/$relpath" 191 fi 192 device=$(readlink /sys/bus/$busname/devices/$target/$relpath/device 2>/dev/null | grep -v /devices/pci) 193 if test "x$device" != x; then 194 savedir "$dest" "/sys/bus/$busname/devices/$target/$relpath/$device" 195 fi 196 done 197} 198 199# savedir "$destdir/$basename" /sys/bus/dax/devices/ 200# readlink /sys/bus/dax/devices/* 2>/dev/null | grep -v /devices/pci | while read -r path ; do savedir "$destdir/$basename" "/sys/bus/dax/devices/$path/.." ; done 201 202# Get an entire mount point, after decoding its path 203# we don't support path with \n since it would break in 'find ... | while read ..." above 204savemntpnt() { 205 local encodedpath=$1 206 if echo "$1" | grep "\\012" ; then 207 echo "Ignoring mount point whose filename contains an end of line." 208 return 209 fi 210 local path=$(echo "$1" | sed -e 's@\\134@\\@g' -e 's@\\040@ @g' -e 's@\\011@ @g') 211 savedir "$destdir/$basename" "${path}/" 212} 213 214# 215# Main stuff 216# 217echo "Gathering main files and directories..." 218 219# Gather the following list of files 220savefile "$destdir/$basename" /proc/cmdline 221savefile "$destdir/$basename" /proc/cpuinfo 222savefile "$destdir/$basename" /proc/meminfo 223savefile "$destdir/$basename" /proc/mounts 224savefile "$destdir/$basename" /proc/stat 225savefile "$destdir/$basename" /proc/version 226savefile "$destdir/$basename" /proc/self/cpuset 227savefile "$destdir/$basename" /proc/self/cgroup 228savefile "$destdir/$basename" /proc/driver/nvidia 229 230# Gather cpu and node information 231# (no need for savebusdir since we already gather the target /sys/devices/system/{cpu,node} explicitly) 232savedir "$destdir/$basename" /sys/devices/system/cpu/ 233savedir "$destdir/$basename" /sys/bus/cpu/devices/ 234savedir "$destdir/$basename" /sys/devices/system/node/ 235savedir "$destdir/$basename" /sys/bus/node/devices/ 236 237# Gather DMI IDs 238# (no need for aveclassdir since we only want "id" and it usually points to /sys/devices/virtual/dmi/id/) 239savedir "$destdir/$basename" /sys/class/dmi/id/ 240savedir "$destdir/$basename" /sys/devices/virtual/dmi/id/ 241 242# Gather hugepage information 243savedir "$destdir/$basename" /sys/kernel/mm/hugepages/ 244 245# Gather the default /var/run/hwloc (in case it was created by a system-wide hwloc-dump-hwdata) 246if test -d /var/run/hwloc; then 247 savedir "$destdir/$basename" /var/run/hwloc 248fi 249# Then, gather what the current hwloc installation could have created in a different $runstatedir 250if test "$runstatedir" != "/var/run" -a -d "$runstatedir/hwloc"; then 251 savedir "$destdir/$basename" "$runstatedir/hwloc/" 252 mkdir -p "$destdir/$basename/var/run" 253 ln -sr "$destdir/$basename/$runstatedir/hwloc" "$destdir/$basename/var/run/hwloc.runstatedir" 254fi 255# And gather what custom $HWLOC_DUMPED_HWDATA_DIR 256if test "x$HWLOC_DUMPED_HWDATA_DIR" != x -a -d "$HWLOC_DUMPED_HWDATA_DIR"; then 257 savedir "$destdir/$basename" "$HWLOC_DUMPED_HWDATA_DIR" 258 mkdir -p "$destdir/$basename/var/run" 259 ln -sr "$destdir/$basename/$HWLOC_DUMPED_HWDATA_DIR" "$destdir/$basename/var/run/hwloc.HWLOC_DUMPED_HWDATA_DIR" 260fi 261# Now link to /var/run/hwloc (used by default in lstopo -i) to something sane if needed 262if ! test -d "$destdir/$basename/var/run/hwloc"; then 263 if test -e "$destdir/$basename/var/run/hwloc.HWLOC_DUMPED_HWDATA_DIR"; then 264 ln -sr "$destdir/$basename/var/run/hwloc.HWLOC_DUMPED_HWDATA_DIR" "$destdir/$basename/var/run/hwloc" 265 else if test -e "$destdir/$basename/$runstatedir/hwloc"; then 266 ln -sr "$destdir/$basename/var/run/hwloc.runstatedir" "$destdir/$basename/var/run/hwloc" 267 fi fi 268fi 269 270# Gather cgroup/cpuset mntpnts 271cat /proc/mounts | while read -r dummy1 mntpath mnttype mntopts dummy2 ; do 272 [ x$mnttype = xcpuset ] && savemntpnt "$mntpath" 273 [ x$mnttype = xcgroup ] && echo $mntopts | grep -w cpuset >/dev/null && savemntpnt "$mntpath" 274 [ x$mnttype = xcgroup2 ] && savemntpnt "$mntpath" 275done 276 277# 278# Optionally gather I/O directories too 279# 280if [ x$gatherio = x1 ]; then 281 echo "Gathering I/O files..." 282 # gather all PCI stuff, lots of links (/sys/bus/pci/devices/* and /sys/class/foo/*) point there 283 savedir "$destdir/$basename" /sys/bus/pci/devices/ 284 savedir "$destdir/$basename" /sys/bus/pci/slots/ 285 ls -d /sys/devices/pci* 2>/dev/null | while read -r path ; do savedir "$destdir/$basename" "$path" ; done 286 # gather class and bus links, we'll parse that the target path for PCI busids 287 saveclassdir "$destdir/$basename" block 288 saveclassdir "$destdir/$basename" dax 289 savebusdir "$destdir/$basename" dax .. 290 saveclassdir "$destdir/$basename" dma 291 saveclassdir "$destdir/$basename" drm 292 saveclassdir "$destdir/$basename" infiniband 293 saveclassdir "$destdir/$basename" net 294 saveclassdir "$destdir/$basename" ve 295 saveclassdir "$destdir/$basename" mic 296 # udev block data 297 ls -d /run/udev/data/b* 2>/dev/null | while read -r path ; do savefile "$destdir/$basename" "$path" ; done 298fi 299 300# 301# Optionally gather DMI directories too 302# 303if [ x$gatherdmi = x1 ]; then 304 echo "Gathering DMI files..." 305 savedir "$destdir/$basename" /sys/firmware/dmi/ 306fi 307 308# 309# Export /proc/hwloc-nofile-info during lstopo (needs HWLOC_DUMP_NOFILE_INFO with HWLOC_THISSYSTEM=1) 310# 311echo "Exporting /proc/hwloc-nofile-info" 312export HWLOC_DUMP_NOFILE_INFO="$destdir/$basename/proc/hwloc-nofile-info" 313"$lstopo" - >/dev/null 314# disable HWLOC_DUMP_NOFILE_INFO for next lstopo invocation 315export HWLOC_DUMP_NOFILE_INFO= 316 317# 318# Export cpuid if available 319# 320if [ x$gathercpuid = x1 -a -e "$hgcpuid" ]; then 321 echo 322 echo "Exporting x86 CPUID using hwloc-gather-cpuid" 323 $hgcpuid --silent "$destdir/$basename/cpuid" 324fi 325 326# Create the archive and optionally keep the tree in /tmp for testing 327echo 328( cd "$destdir/" && tar cfj "$basename.tar.bz2" "$basename" ) 329mv "$destdir/$basename.tar.bz2" "$dirname/$basename.tar.bz2" 330if test x$keep = x1; then 331 echo "Topology files gathered in $dirname/$basename.tar.bz2 and kept in $destdir/$basename/" 332else 333 echo "Topology files gathered in $dirname/$basename.tar.bz2" 334 rm -rf "$destdir" 335fi 336 337# Generate the output as well 338# we need "Topology not from this system" in the output so as to make test-topology.sh happy 339export HWLOC_THISSYSTEM=0 340"$lstopo" - -v > "$dirname/$basename.output" 341echo "Expected topology output stored in $dirname/$basename.output" 342"$lstopo" -.xml --whole-io --disallowed > "$dirname/$basename.xml" 343echo "XML topology stored in $dirname/$basename.xml" 344 345echo 346echo "WARNING: Do not post these files on a public list or website unless you" 347echo "WARNING: are sure that no information about this platform is sensitive." 348 349exit 0 350