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