Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+94 −7
Original line number Original line Diff line number Diff line
@@ -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;
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 = {
	.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)
	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)
	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)
	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;