Commit 12e0c95e authored by Frank Munzert's avatar Frank Munzert Committed by Heiko Carstens

[S390] zfcpdump: Make SCSI disk dump tool recognize storage holes

The kernel part of zfcpdump establishes a new debugfs file zcore/memmap
which exports information on memory layout (start address and length of each
memory chunk) to its userspace counterpart.
Signed-off-by: default avatarFrank Munzert <munzert@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
parent 33af79d1
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define TO_USER 0 #define TO_USER 0
#define TO_KERNEL 1 #define TO_KERNEL 1
#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
enum arch_id { enum arch_id {
ARCH_S390 = 0, ARCH_S390 = 0,
...@@ -51,6 +52,7 @@ static struct debug_info *zcore_dbf; ...@@ -51,6 +52,7 @@ static struct debug_info *zcore_dbf;
static int hsa_available; static int hsa_available;
static struct dentry *zcore_dir; static struct dentry *zcore_dir;
static struct dentry *zcore_file; static struct dentry *zcore_file;
static struct dentry *zcore_memmap_file;
/* /*
* Copy memory from HSA to kernel or user memory (not reentrant): * Copy memory from HSA to kernel or user memory (not reentrant):
...@@ -476,6 +478,54 @@ static const struct file_operations zcore_fops = { ...@@ -476,6 +478,54 @@ static const struct file_operations zcore_fops = {
.release = zcore_release, .release = zcore_release,
}; };
static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
return simple_read_from_buffer(buf, count, ppos, filp->private_data,
MEMORY_CHUNKS * CHUNK_INFO_SIZE);
}
static int zcore_memmap_open(struct inode *inode, struct file *filp)
{
int i;
char *buf;
struct mem_chunk *chunk_array;
chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
GFP_KERNEL);
if (!chunk_array)
return -ENOMEM;
detect_memory_layout(chunk_array);
buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
if (!buf) {
kfree(chunk_array);
return -ENOMEM;
}
for (i = 0; i < MEMORY_CHUNKS; i++) {
sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
(unsigned long long) chunk_array[i].addr,
(unsigned long long) chunk_array[i].size);
if (chunk_array[i].size == 0)
break;
}
kfree(chunk_array);
filp->private_data = buf;
return 0;
}
static int zcore_memmap_release(struct inode *inode, struct file *filp)
{
kfree(filp->private_data);
return 0;
}
static const struct file_operations zcore_memmap_fops = {
.owner = THIS_MODULE,
.read = zcore_memmap_read,
.open = zcore_memmap_open,
.release = zcore_memmap_release,
};
static void __init set_s390_lc_mask(union save_area *map) static void __init set_s390_lc_mask(union save_area *map)
{ {
...@@ -554,18 +604,44 @@ static int __init check_sdias(void) ...@@ -554,18 +604,44 @@ static int __init check_sdias(void)
return 0; return 0;
} }
static void __init zcore_header_init(int arch, struct zcore_header *hdr) static int __init get_mem_size(unsigned long *mem)
{
int i;
struct mem_chunk *chunk_array;
chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
GFP_KERNEL);
if (!chunk_array)
return -ENOMEM;
detect_memory_layout(chunk_array);
for (i = 0; i < MEMORY_CHUNKS; i++) {
if (chunk_array[i].size == 0)
break;
*mem += chunk_array[i].size;
}
kfree(chunk_array);
return 0;
}
static int __init zcore_header_init(int arch, struct zcore_header *hdr)
{ {
int rc;
unsigned long memory = 0;
if (arch == ARCH_S390X) if (arch == ARCH_S390X)
hdr->arch_id = DUMP_ARCH_S390X; hdr->arch_id = DUMP_ARCH_S390X;
else else
hdr->arch_id = DUMP_ARCH_S390; hdr->arch_id = DUMP_ARCH_S390;
hdr->mem_size = sys_info.mem_size; rc = get_mem_size(&memory);
hdr->rmem_size = sys_info.mem_size; if (rc)
return rc;
hdr->mem_size = memory;
hdr->rmem_size = memory;
hdr->mem_end = sys_info.mem_size; hdr->mem_end = sys_info.mem_size;
hdr->num_pages = sys_info.mem_size / PAGE_SIZE; hdr->num_pages = memory / PAGE_SIZE;
hdr->tod = get_clock(); hdr->tod = get_clock();
get_cpu_id(&hdr->cpu_id); get_cpu_id(&hdr->cpu_id);
return 0;
} }
static int __init zcore_init(void) static int __init zcore_init(void)
...@@ -608,7 +684,9 @@ static int __init zcore_init(void) ...@@ -608,7 +684,9 @@ static int __init zcore_init(void)
if (rc) if (rc)
goto fail; goto fail;
zcore_header_init(arch, &zcore_header); rc = zcore_header_init(arch, &zcore_header);
if (rc)
goto fail;
zcore_dir = debugfs_create_dir("zcore" , NULL); zcore_dir = debugfs_create_dir("zcore" , NULL);
if (!zcore_dir) { if (!zcore_dir) {
...@@ -618,13 +696,22 @@ static int __init zcore_init(void) ...@@ -618,13 +696,22 @@ static int __init zcore_init(void)
zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL, zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,
&zcore_fops); &zcore_fops);
if (!zcore_file) { if (!zcore_file) {
debugfs_remove(zcore_dir);
rc = -ENOMEM; rc = -ENOMEM;
goto fail; goto fail_dir;
}
zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir,
NULL, &zcore_memmap_fops);
if (!zcore_memmap_file) {
rc = -ENOMEM;
goto fail_file;
} }
hsa_available = 1; hsa_available = 1;
return 0; return 0;
fail_file:
debugfs_remove(zcore_file);
fail_dir:
debugfs_remove(zcore_dir);
fail: fail:
diag308(DIAG308_REL_HSA, NULL); diag308(DIAG308_REL_HSA, NULL);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment