mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
This commit is based on the s390-tools-1.39.0 version. Changes on top of s390-tools-1.39.0: - Add MIT license to all source files - Add LICENSE file - Transform REAMDE to README.md (markdown) - Add AUTHORS.md file - Add CONTRIBUTING.md file - Move changelog from README to CHANGELOG.md file Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
173 lines
4.3 KiB
Perl
Executable File
173 lines
4.3 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# lsmem - Tool to show memory hotplug status
|
|
#
|
|
# Copyright IBM Corp. 2010, 2017
|
|
#
|
|
# s390-tools is free software; you can redistribute it and/or modify
|
|
# it under the terms of the MIT license. See LICENSE for details.
|
|
#
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Getopt::Long qw(:config no_ignore_case no_auto_abbrev);
|
|
use File::Basename;
|
|
|
|
my $script_name = fileparse($0);
|
|
my $memdir = "/sys/devices/system/memory";
|
|
my $block_size = 0;
|
|
my $list_all = 0;
|
|
my $dev_size = 0;
|
|
my @entries;
|
|
|
|
|
|
sub lsmem_read_attr($$$$)
|
|
# parameters: state, rem, device, block_nr
|
|
{
|
|
my @attributes = qw(state removable phys_device);
|
|
foreach (0..2) {
|
|
$_[$_] = `cat $memdir/memory$_[3]/$attributes[$_]`;
|
|
chomp($_[$_]);
|
|
}
|
|
}
|
|
|
|
sub lsmem_get_dev_size()
|
|
{
|
|
my ($device, $old_device, $block, $old_block) = (0, 0, 0, 0);
|
|
|
|
foreach (@entries) {
|
|
$_ =~ /memory(\d+)/;
|
|
$block = $1;
|
|
$device = `cat $_/phys_device`;
|
|
chomp($device);
|
|
if ($device > $old_device) {
|
|
$dev_size = int((($block - $old_block) * $block_size) /
|
|
($device - $old_device));
|
|
last;
|
|
}
|
|
$dev_size += $block_size;
|
|
$old_block = $block;
|
|
}
|
|
}
|
|
|
|
sub lsmem_list()
|
|
{
|
|
my $block = 0;
|
|
my ($start, $end, $size) = (0, 0, 0);
|
|
my ($state, $next_state) = (0, 0);
|
|
my ($rem, $next_rem) = (0, 0);
|
|
my ($device, $next_device, $end_dev) = (0, 0, 0);
|
|
my ($mem_online, $mem_offline) = (0, 0);
|
|
my $mem_hole;
|
|
|
|
$block_size = `cat $memdir/block_size_bytes`;
|
|
chomp($block_size);
|
|
if ($block_size =~ /(?:0x)?([[:xdigit:]]+)/) {
|
|
$block_size = unpack("Q", pack("H16",
|
|
substr("0" x 16 . $1, -16)));
|
|
$block_size = $block_size >> 20;
|
|
} else {
|
|
die "lsmem: Unknown block size format in sysfs.\n";
|
|
}
|
|
lsmem_get_dev_size();
|
|
# Start with $mem_hole = 1 to initialize $start, $state, $rem, $device
|
|
$mem_hole = 1;
|
|
|
|
print <<HERE;
|
|
Address Range Size (MB) State Removable Device
|
|
===============================================================================
|
|
HERE
|
|
foreach (@entries) {
|
|
$_ =~ /memory(\d+)/;
|
|
$block = $1;
|
|
if ($mem_hole) {
|
|
lsmem_read_attr($state, $rem, $device, $block);
|
|
$start = ($block) * ($block_size << 20);
|
|
$mem_hole = 0;
|
|
}
|
|
# check next block or memory hole
|
|
$block++;
|
|
if (-d "$memdir/memory".$block) {
|
|
lsmem_read_attr($next_state, $next_rem, $next_device,
|
|
$block);
|
|
} else {
|
|
$mem_hole = 1
|
|
}
|
|
if ($state ne $next_state || $rem != $next_rem || $list_all ||
|
|
$mem_hole) {
|
|
$end = ($block) * ($block_size << 20) - 1;
|
|
$size = ($end - $start + 1) >> 20;
|
|
if ($state eq "going-offline") {
|
|
$state = "on->off";
|
|
}
|
|
printf("0x%016x-0x%016x %10lu %-7s ", $start, $end,
|
|
$size, $state);
|
|
if ($state eq "online") {
|
|
printf(" %-9s ", $rem ? "yes" : "no");
|
|
$mem_online += $size;
|
|
} else {
|
|
printf(" %-9s ", "-");
|
|
$mem_offline += $size;
|
|
}
|
|
$end_dev = ($end / $dev_size) >> 20;
|
|
if ($device == $end_dev) {
|
|
printf("%d\n", $device);
|
|
} else {
|
|
printf("%d-%d\n", $device, $end_dev);
|
|
}
|
|
$state = $next_state;
|
|
$rem = $next_rem;
|
|
$device = $end_dev + 1;
|
|
$start = $end + 1;
|
|
}
|
|
}
|
|
printf("\n");
|
|
printf("Memory device size : %lu MB\n", $dev_size);
|
|
printf("Memory block size : %lu MB\n", $block_size);
|
|
printf("Total online memory : %lu MB\n", $mem_online);
|
|
printf("Total offline memory: %lu MB\n", $mem_offline);
|
|
}
|
|
|
|
sub lsmem_usage()
|
|
{
|
|
print <<HERE;
|
|
Usage: $script_name [OPTIONS]
|
|
|
|
The $script_name command lists the ranges of available memory with their online
|
|
status. The listed memory blocks correspond to the memory block representation
|
|
in sysfs. The command also shows the memory block size, the device size, and
|
|
the amount of memory in online and offline state.
|
|
|
|
OPTIONS
|
|
-a, --all
|
|
List each individual memory block, instead of combining memory blocks
|
|
with similar attributes.
|
|
|
|
-h, --help
|
|
Print a short help text, then exit.
|
|
|
|
-v, --version
|
|
Print the version number, then exit.
|
|
HERE
|
|
}
|
|
|
|
sub lsmem_version()
|
|
{
|
|
print "$script_name: version %S390_TOOLS_VERSION%\n";
|
|
print "Copyright IBM Corp. 2010, 2017\n";
|
|
}
|
|
|
|
|
|
# Main
|
|
unless (GetOptions('v|version' => sub {lsmem_version(); exit 0;},
|
|
'h|help' => sub {lsmem_usage(); exit 0;},
|
|
'a|all' => \$list_all)) {
|
|
die "Try '$script_name --help' for more information.\n";
|
|
};
|
|
|
|
@entries = (sort {length($a) <=> length($b) || $a cmp $b} <$memdir/memory*>);
|
|
if (@entries == 0) {
|
|
die "lsmem: No memory hotplug interface in sysfs ($memdir).\n";
|
|
}
|
|
lsmem_list();
|