s390/zcore: Add hsa file
Under LPAR the zfcpdump HSA is a shared resource. Up to now the HSA memory
is released when the zcore file is closed. Dump programs that know that
they do not need the HSA memory any more (e.g. because they already dumped it)
could release it earlier. This would allow other LPARs to use it again.
To achieve this a new debugfs file "hsa" is added that can be used to read
the HSA size and to release the HSA by writing "0" into the file.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index e3b9308..681749e 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -62,6 +62,7 @@
static struct dentry *zcore_file;
static struct dentry *zcore_memmap_file;
static struct dentry *zcore_reipl_file;
+static struct dentry *zcore_hsa_file;
static struct ipl_parameter_block *ipl_block;
/*
@@ -77,6 +78,8 @@
int offs, blk_num;
static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+ if (!hsa_available)
+ return -ENODATA;
if (count == 0)
return 0;
@@ -278,6 +281,15 @@
}
/*
+ * Release the HSA
+ */
+static void release_hsa(void)
+{
+ diag308(DIAG308_REL_HSA, NULL);
+ hsa_available = 0;
+}
+
+/*
* Read routine for zcore character device
* First 4K are dump header
* Next 32MB are HSA Memory
@@ -363,8 +375,8 @@
static int zcore_release(struct inode *inode, struct file *filep)
{
- diag308(DIAG308_REL_HSA, NULL);
- hsa_available = 0;
+ if (hsa_available)
+ release_hsa();
return 0;
}
@@ -474,6 +486,41 @@
.llseek = no_llseek,
};
+static ssize_t zcore_hsa_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ static char str[18];
+
+ if (hsa_available)
+ snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE);
+ else
+ snprintf(str, sizeof(str), "0\n");
+ return simple_read_from_buffer(buf, count, ppos, str, strlen(str));
+}
+
+static ssize_t zcore_hsa_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char value;
+
+ if (*ppos != 0)
+ return -EPIPE;
+ if (copy_from_user(&value, buf, 1))
+ return -EFAULT;
+ if (value != '0')
+ return -EINVAL;
+ release_hsa();
+ return count;
+}
+
+static const struct file_operations zcore_hsa_fops = {
+ .owner = THIS_MODULE,
+ .write = zcore_hsa_write,
+ .read = zcore_hsa_read,
+ .open = nonseekable_open,
+ .llseek = no_llseek,
+};
+
#ifdef CONFIG_32BIT
static void __init set_lc_mask(struct save_area *map)
@@ -658,6 +705,7 @@
rc = check_sdias();
if (rc)
goto fail;
+ hsa_available = 1;
rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1);
if (rc)
@@ -714,9 +762,16 @@
rc = -ENOMEM;
goto fail_memmap_file;
}
- hsa_available = 1;
+ zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir,
+ NULL, &zcore_hsa_fops);
+ if (!zcore_hsa_file) {
+ rc = -ENOMEM;
+ goto fail_reipl_file;
+ }
return 0;
+fail_reipl_file:
+ debugfs_remove(zcore_reipl_file);
fail_memmap_file:
debugfs_remove(zcore_memmap_file);
fail_file:
@@ -733,6 +788,7 @@
debug_unregister(zcore_dbf);
sclp_sdias_exit();
free_page((unsigned long) ipl_block);
+ debugfs_remove(zcore_hsa_file);
debugfs_remove(zcore_reipl_file);
debugfs_remove(zcore_memmap_file);
debugfs_remove(zcore_file);