File s390-tools-sles11sp2-lsmem-chmem-memory_hole.patch of Package s390-tools
Description: lsmem/chmem: Fix handling of memory holes
Symptom: When using memory holes, lsmem doesn't show the memory after a
hole and chmem doesn't work.
Problem: Wrong assumption that memory block numbers are contiguous.
Solution: Make it work with non-contiguous memory block numbers.
Problem-ID: 75392
---
zconf/chmem | 40 ++++++++++++++------------
zconf/lsmem | 89 +++++++++++++++++++++++++++++++++---------------------------
2 files changed, 72 insertions(+), 57 deletions(-)
--- a/zconf/chmem
+++ b/zconf/chmem
@@ -2,7 +2,7 @@
###############################################################################
# chmem - script to show memory hotplug status.
#
-# Copyright IBM Corp. 2010
+# Copyright IBM Corp. 2010, 2011
# Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
###############################################################################
@@ -22,6 +22,7 @@ my $dev_size;
my $blocks_per_dev = 0;
my $devs_per_block = 0;
my $ret = 0;
+my @entries;
sub chmem_usage()
{
@@ -60,24 +61,24 @@ HERE
sub chmem_version()
{
print "$script_name: version %S390_TOOLS_VERSION%\n";
- print "Copyright IBM Corp. 2010\n";
+ print "Copyright IBM Corp. 2010, 2011\n";
}
sub chmem_get_dev_size()
{
- my $i = 0;
- my $device = 0;
- my $old_device = 0;
+ my ($device, $old_device, $block, $old_block) = (0, 0, 0, 0);
- while (-d "$memdir/memory$i") {
- $device = `cat $memdir/memory$i/phys_device`;
+ foreach (@entries) {
+ $_ =~ /memory(\d+)/;
+ $block = $1;
+ $device = `cat $_/phys_device`;
chomp($device);
if ($device > $old_device) {
- $dev_size = int($dev_size / ($device - $old_device));
+ $dev_size = int((($block - $old_block) * $block_size) /
+ ($device - $old_device));
last;
}
- $dev_size += $block_size;
- $i++;
+ $old_block = $block;
}
}
@@ -109,14 +110,16 @@ sub chmem_read_attr($$$)
sub chmem_read_devices()
{
- my $i = 0;
+ my $block = 0;
my $device = 0;
my $old_device = 0;
my $blocks = 0;
my $state;
- while (-d "$memdir/memory$i") {
- chmem_read_attr($state, $device, $i);
+ foreach (@entries) {
+ $_ =~ /memory(\d+)/;
+ $block = $1;
+ chmem_read_attr($state, $device, $block);
if ($device != $old_device) {
$devices->{$old_device}->{'id'} = $old_device;
$devices->{$old_device}->{'blocks'} = $blocks;
@@ -126,7 +129,6 @@ sub chmem_read_devices()
if ($state eq "online") {
$blocks++;
}
- $i++;
}
$devices->{$old_device}->{'blocks'} = $blocks;
$devices->{$old_device}->{'id'} = $old_device;
@@ -244,9 +246,6 @@ sub chmem_range($$)
sub chmem_check()
{
- unless (-d $memdir) {
- die "chmem: No memory hotplug interface in sysfs ($memdir).\n";
- }
$block_size = `cat $memdir/block_size_bytes`;
chomp($block_size);
if ($block_size =~ /(?:0x)?([[:xdigit:]]+)/) {
@@ -263,7 +262,7 @@ sub chmem_check()
die "chmem: You cannot specify both options -e and -d.\n";
}
- while (-d "$memdir/memory$total_blocks") {
+ foreach (@entries) {
$total_blocks++;
}
chmem_get_dev_size();
@@ -319,6 +318,11 @@ unless (GetOptions('v|version' => sub {c
die "Try '$script_name --help' for more information.\n";
};
+@entries = (sort {length($a) <=> length($b) || $a cmp $b} <$memdir/memory*>);
+if (@entries == 0) {
+ die "chmem: No memory hotplug interface in sysfs ($memdir).\n";
+}
+
chmem_read_devices();
chmem_check();
chmem_action();
--- a/zconf/lsmem
+++ b/zconf/lsmem
@@ -2,7 +2,7 @@
###############################################################################
# lsmem - script to show memory hotplug status.
#
-# Copyright IBM Corp. 2010
+# Copyright IBM Corp. 2010, 2011
# Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
###############################################################################
@@ -16,6 +16,7 @@ my $memdir = "/sys/devices/system/memory
my $block_size = 0;
my $list_all = 0;
my $dev_size = 0;
+my @entries;
sub lsmem_read_attr($$$$)
@@ -30,36 +31,31 @@ sub lsmem_read_attr($$$$)
sub lsmem_get_dev_size()
{
- my $i = 0;
- my ($device, $old_device) = (0, 0);
+ my ($device, $old_device, $block, $old_block) = (0, 0, 0, 0);
- while (-d "$memdir/memory$i") {
- $device = `cat $memdir/memory$i/phys_device`;
+ foreach (@entries) {
+ $_ =~ /memory(\d+)/;
+ $block = $1;
+ $device = `cat $_/phys_device`;
chomp($device);
if ($device > $old_device) {
- $dev_size = int($dev_size / ($device - $old_device));
+ $dev_size = int((($block - $old_block) * $block_size) /
+ ($device - $old_device));
last;
}
- $dev_size += $block_size;
- $i++;
+ $old_block = $block;
}
}
sub lsmem_list()
{
- my $i = 0;
+ my $block = 0;
my ($start, $end, $size) = (0, 0, 0);
- my ($state, $old_state) = (0, 0);
- my ($rem, $old_rem) = (0, 0);
- my ($device, $old_device) = (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 ($last_block, $end_dev) = (0, 0);
-
- if (-d "$memdir/memory0") {
- lsmem_read_attr($old_state, $old_rem, $old_device, 0);
- } else {
- die "lsmem: No memory hotplug interface in sysfs ($memdir).\n";
- }
+ my $mem_hole;
$block_size = `cat $memdir/block_size_bytes`;
chomp($block_size);
@@ -71,43 +67,54 @@ sub lsmem_list()
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
- while (-d "$memdir/memory$i") {
- $i++;
- if (-d "$memdir/memory$i") {
- lsmem_read_attr($state, $rem, $device, $i);
+ 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 {
- $last_block = 1;
+ $mem_hole = 1
}
- if ($state ne $old_state || $rem != $old_rem || $list_all ||
- $last_block) {
- $end = $i * ($block_size << 20) - 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 ($old_state eq "going-offline") {
- $old_state = "on->off";
+ if ($state eq "going-offline") {
+ $state = "on->off";
}
printf("0x%016x-0x%016x %10lu %-7s ", $start, $end,
- $size, $old_state);
- if ($old_state eq "online") {
- printf(" %-9s ", $old_rem ? "yes" : "no");
+ $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 ($old_device == $end_dev) {
- printf("%d\n", $old_device);
+ if ($device == $end_dev) {
+ printf("%d\n", $device);
} else {
- printf("%d-%d\n", $old_device, $end_dev);
+ printf("%d-%d\n", $device, $end_dev);
}
- $old_state = $state;
- $old_rem = $rem;
- $old_device = $device;
+ $state = $next_state;
+ $rem = $next_rem;
+ $device = $end_dev + 1;
$start = $end + 1;
}
}
@@ -144,7 +151,7 @@ HERE
sub lsmem_version()
{
print "$script_name: version %S390_TOOLS_VERSION%\n";
- print "Copyright IBM Corp. 2010\n";
+ print "Copyright IBM Corp. 2010, 2011\n";
}
@@ -155,4 +162,8 @@ unless (GetOptions('v|version' => sub {l
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();