aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/hypfs
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/hypfs')
-rw-r--r--arch/s390/hypfs/Makefile2
-rw-r--r--arch/s390/hypfs/hypfs.h56
-rw-r--r--arch/s390/hypfs/hypfs_dbfs.c130
-rw-r--r--arch/s390/hypfs/hypfs_diag.c140
-rw-r--r--arch/s390/hypfs/hypfs_sprp.c141
-rw-r--r--arch/s390/hypfs/hypfs_vm.c136
-rw-r--r--arch/s390/hypfs/inode.c129
7 files changed, 484 insertions, 250 deletions
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
index b08d2abf617..06f8d95a16c 100644
--- a/arch/s390/hypfs/Makefile
+++ b/arch/s390/hypfs/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
-s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o
+s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o hypfs_sprp.o
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
index fa487d4cc08..b34b5ab90a3 100644
--- a/arch/s390/hypfs/hypfs.h
+++ b/arch/s390/hypfs/hypfs.h
@@ -1,8 +1,7 @@
/*
- * arch/s390/hypfs/hypfs.h
* Hypervisor filesystem for Linux on s390.
*
- * Copyright (C) IBM Corp. 2006
+ * Copyright IBM Corp. 2006
* Author(s): Michael Holzheu <holzheu@de.ibm.com>
*/
@@ -12,32 +11,65 @@
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/debugfs.h>
+#include <linux/workqueue.h>
+#include <linux/kref.h>
+#include <asm/hypfs.h>
#define REG_FILE_MODE 0440
#define UPDATE_FILE_MODE 0220
#define DIR_MODE 0550
-extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
- const char *name);
+extern struct dentry *hypfs_mkdir(struct dentry *parent, const char *name);
-extern struct dentry *hypfs_create_u64(struct super_block *sb,
- struct dentry *dir, const char *name,
+extern struct dentry *hypfs_create_u64(struct dentry *dir, const char *name,
__u64 value);
-extern struct dentry *hypfs_create_str(struct super_block *sb,
- struct dentry *dir, const char *name,
+extern struct dentry *hypfs_create_str(struct dentry *dir, const char *name,
char *string);
/* LPAR Hypervisor */
extern int hypfs_diag_init(void);
extern void hypfs_diag_exit(void);
-extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+extern int hypfs_diag_create_files(struct dentry *root);
/* VM Hypervisor */
extern int hypfs_vm_init(void);
extern void hypfs_vm_exit(void);
-extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root);
+extern int hypfs_vm_create_files(struct dentry *root);
+
+/* Set Partition-Resource Parameter */
+int hypfs_sprp_init(void);
+void hypfs_sprp_exit(void);
+
+/* debugfs interface */
+struct hypfs_dbfs_file;
+
+struct hypfs_dbfs_data {
+ void *buf;
+ void *buf_free_ptr;
+ size_t size;
+ struct hypfs_dbfs_file *dbfs_file;
+ struct kref kref;
+};
+
+struct hypfs_dbfs_file {
+ const char *name;
+ int (*data_create)(void **data, void **data_free_ptr,
+ size_t *size);
+ void (*data_free)(const void *buf_free_ptr);
+ long (*unlocked_ioctl) (struct file *, unsigned int,
+ unsigned long);
+
+ /* Private data for hypfs_dbfs.c */
+ struct hypfs_dbfs_data *data;
+ struct delayed_work data_free_work;
+ struct mutex lock;
+ struct dentry *dentry;
+};
+
+extern int hypfs_dbfs_init(void);
+extern void hypfs_dbfs_exit(void);
+extern int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df);
+extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df);
-/* Directory for debugfs files */
-extern struct dentry *hypfs_dbfs_dir;
#endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
new file mode 100644
index 00000000000..2badf2bf9cd
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_dbfs.c
@@ -0,0 +1,130 @@
+/*
+ * Hypervisor filesystem for Linux on s390 - debugfs interface
+ *
+ * Copyright IBM Corp. 2010
+ * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
+ */
+
+#include <linux/slab.h>
+#include "hypfs.h"
+
+static struct dentry *dbfs_dir;
+
+static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f)
+{
+ struct hypfs_dbfs_data *data;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+ kref_init(&data->kref);
+ data->dbfs_file = f;
+ return data;
+}
+
+static void hypfs_dbfs_data_free(struct kref *kref)
+{
+ struct hypfs_dbfs_data *data;
+
+ data = container_of(kref, struct hypfs_dbfs_data, kref);
+ data->dbfs_file->data_free(data->buf_free_ptr);
+ kfree(data);
+}
+
+static void data_free_delayed(struct work_struct *work)
+{
+ struct hypfs_dbfs_data *data;
+ struct hypfs_dbfs_file *df;
+
+ df = container_of(work, struct hypfs_dbfs_file, data_free_work.work);
+ mutex_lock(&df->lock);
+ data = df->data;
+ df->data = NULL;
+ mutex_unlock(&df->lock);
+ kref_put(&data->kref, hypfs_dbfs_data_free);
+}
+
+static ssize_t dbfs_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ struct hypfs_dbfs_data *data;
+ struct hypfs_dbfs_file *df;
+ ssize_t rc;
+
+ if (*ppos != 0)
+ return 0;
+
+ df = file_inode(file)->i_private;
+ mutex_lock(&df->lock);
+ if (!df->data) {
+ data = hypfs_dbfs_data_alloc(df);
+ if (!data) {
+ mutex_unlock(&df->lock);
+ return -ENOMEM;
+ }
+ rc = df->data_create(&data->buf, &data->buf_free_ptr,
+ &data->size);
+ if (rc) {
+ mutex_unlock(&df->lock);
+ kfree(data);
+ return rc;
+ }
+ df->data = data;
+ schedule_delayed_work(&df->data_free_work, HZ);
+ }
+ data = df->data;
+ kref_get(&data->kref);
+ mutex_unlock(&df->lock);
+
+ rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
+ kref_put(&data->kref, hypfs_dbfs_data_free);
+ return rc;
+}
+
+static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hypfs_dbfs_file *df;
+ long rc;
+
+ df = file->f_path.dentry->d_inode->i_private;
+ mutex_lock(&df->lock);
+ if (df->unlocked_ioctl)
+ rc = df->unlocked_ioctl(file, cmd, arg);
+ else
+ rc = -ENOTTY;
+ mutex_unlock(&df->lock);
+ return rc;
+}
+
+static const struct file_operations dbfs_ops = {
+ .read = dbfs_read,
+ .llseek = no_llseek,
+ .unlocked_ioctl = dbfs_ioctl,
+};
+
+int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
+{
+ df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
+ &dbfs_ops);
+ if (IS_ERR(df->dentry))
+ return PTR_ERR(df->dentry);
+ mutex_init(&df->lock);
+ INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed);
+ return 0;
+}
+
+void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
+{
+ debugfs_remove(df->dentry);
+}
+
+int hypfs_dbfs_init(void)
+{
+ dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
+ return PTR_ERR_OR_ZERO(dbfs_dir);
+}
+
+void hypfs_dbfs_exit(void)
+{
+ debugfs_remove(dbfs_dir);
+}
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index cd4a81be9cf..5eeffeefae0 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -1,5 +1,4 @@
/*
- * arch/s390/hypfs/hypfs_diag.c
* Hypervisor filesystem for Linux on s390. Diag 204 and 224
* implementation.
*
@@ -555,81 +554,37 @@ struct dbfs_d204 {
char buf[]; /* d204 buffer */
} __attribute__ ((packed));
-struct dbfs_d204_private {
- struct dbfs_d204 *d204; /* Aligned d204 data with header */
- void *base; /* Base pointer (needed for vfree) */
-};
-
-static int dbfs_d204_open(struct inode *inode, struct file *file)
+static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size)
{
- struct dbfs_d204_private *data;
struct dbfs_d204 *d204;
int rc, buf_size;
+ void *base;
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr);
- data->base = vmalloc(buf_size);
- if (!data->base) {
- rc = -ENOMEM;
- goto fail_kfree_data;
+ base = vzalloc(buf_size);
+ if (!base)
+ return -ENOMEM;
+ d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr);
+ rc = diag204_do_store(d204->buf, diag204_buf_pages);
+ if (rc) {
+ vfree(base);
+ return rc;
}
- memset(data->base, 0, buf_size);
- d204 = page_align_ptr(data->base + sizeof(d204->hdr))
- - sizeof(d204->hdr);
- rc = diag204_do_store(&d204->buf, diag204_buf_pages);
- if (rc)
- goto fail_vfree_base;
d204->hdr.version = DBFS_D204_HDR_VERSION;
d204->hdr.len = PAGE_SIZE * diag204_buf_pages;
d204->hdr.sc = diag204_store_sc;
- data->d204 = d204;
- file->private_data = data;
- return nonseekable_open(inode, file);
-
-fail_vfree_base:
- vfree(data->base);
-fail_kfree_data:
- kfree(data);
- return rc;
-}
-
-static int dbfs_d204_release(struct inode *inode, struct file *file)
-{
- struct dbfs_d204_private *data = file->private_data;
-
- vfree(data->base);
- kfree(data);
+ *data = d204;
+ *data_free_ptr = base;
+ *size = d204->hdr.len + sizeof(struct dbfs_d204_hdr);
return 0;
}
-static ssize_t dbfs_d204_read(struct file *file, char __user *buf,
- size_t size, loff_t *ppos)
-{
- struct dbfs_d204_private *data = file->private_data;
-
- return simple_read_from_buffer(buf, size, ppos, data->d204,
- data->d204->hdr.len +
- sizeof(data->d204->hdr));
-}
-
-static const struct file_operations dbfs_d204_ops = {
- .open = dbfs_d204_open,
- .read = dbfs_d204_read,
- .release = dbfs_d204_release,
- .llseek = no_llseek,
+static struct hypfs_dbfs_file dbfs_file_d204 = {
+ .name = "diag_204",
+ .data_create = dbfs_d204_create,
+ .data_free = vfree,
};
-static int hypfs_dbfs_init(void)
-{
- dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir,
- NULL, &dbfs_d204_ops);
- if (IS_ERR(dbfs_d204_file))
- return PTR_ERR(dbfs_d204_file);
- return 0;
-}
-
__init int hypfs_diag_init(void)
{
int rc;
@@ -639,7 +594,7 @@ __init int hypfs_diag_init(void)
return -ENODATA;
}
if (diag204_info_type == INFO_EXT) {
- rc = hypfs_dbfs_init();
+ rc = hypfs_dbfs_create_file(&dbfs_file_d204);
if (rc)
return rc;
}
@@ -660,6 +615,7 @@ void hypfs_diag_exit(void)
debugfs_remove(dbfs_d204_file);
diag224_delete_name_table();
diag204_free_buffer();
+ hypfs_dbfs_remove_file(&dbfs_file_d204);
}
/*
@@ -667,8 +623,7 @@ void hypfs_diag_exit(void)
* *******************************************
*/
-static int hypfs_create_cpu_files(struct super_block *sb,
- struct dentry *cpus_dir, void *cpu_info)
+static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info)
{
struct dentry *cpu_dir;
char buffer[TMP_SIZE];
@@ -676,32 +631,29 @@ static int hypfs_create_cpu_files(struct super_block *sb,
snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
cpu_info));
- cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
- rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+ cpu_dir = hypfs_mkdir(cpus_dir, buffer);
+ rc = hypfs_create_u64(cpu_dir, "mgmtime",
cpu_info__acc_time(diag204_info_type, cpu_info) -
cpu_info__lp_time(diag204_info_type, cpu_info));
if (IS_ERR(rc))
return PTR_ERR(rc);
- rc = hypfs_create_u64(sb, cpu_dir, "cputime",
+ rc = hypfs_create_u64(cpu_dir, "cputime",
cpu_info__lp_time(diag204_info_type, cpu_info));
if (IS_ERR(rc))
return PTR_ERR(rc);
if (diag204_info_type == INFO_EXT) {
- rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",
+ rc = hypfs_create_u64(cpu_dir, "onlinetime",
cpu_info__online_time(diag204_info_type,
cpu_info));
if (IS_ERR(rc))
return PTR_ERR(rc);
}
diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
- rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
- if (IS_ERR(rc))
- return PTR_ERR(rc);
- return 0;
+ rc = hypfs_create_str(cpu_dir, "type", buffer);
+ return PTR_RET(rc);
}
-static void *hypfs_create_lpar_files(struct super_block *sb,
- struct dentry *systems_dir, void *part_hdr)
+static void *hypfs_create_lpar_files(struct dentry *systems_dir, void *part_hdr)
{
struct dentry *cpus_dir;
struct dentry *lpar_dir;
@@ -711,16 +663,16 @@ static void *hypfs_create_lpar_files(struct super_block *sb,
part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
lpar_name[LPAR_NAME_LEN] = 0;
- lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);
+ lpar_dir = hypfs_mkdir(systems_dir, lpar_name);
if (IS_ERR(lpar_dir))
return lpar_dir;
- cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");
+ cpus_dir = hypfs_mkdir(lpar_dir, "cpus");
if (IS_ERR(cpus_dir))
return cpus_dir;
cpu_info = part_hdr + part_hdr__size(diag204_info_type);
for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
int rc;
- rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
+ rc = hypfs_create_cpu_files(cpus_dir, cpu_info);
if (rc)
return ERR_PTR(rc);
cpu_info += cpu_info__size(diag204_info_type);
@@ -728,8 +680,7 @@ static void *hypfs_create_lpar_files(struct super_block *sb,
return cpu_info;
}
-static int hypfs_create_phys_cpu_files(struct super_block *sb,
- struct dentry *cpus_dir, void *cpu_info)
+static int hypfs_create_phys_cpu_files(struct dentry *cpus_dir, void *cpu_info)
{
struct dentry *cpu_dir;
char buffer[TMP_SIZE];
@@ -737,34 +688,31 @@ static int hypfs_create_phys_cpu_files(struct super_block *sb,
snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
cpu_info));
- cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+ cpu_dir = hypfs_mkdir(cpus_dir, buffer);
if (IS_ERR(cpu_dir))
return PTR_ERR(cpu_dir);
- rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+ rc = hypfs_create_u64(cpu_dir, "mgmtime",
phys_cpu__mgm_time(diag204_info_type, cpu_info));
if (IS_ERR(rc))
return PTR_ERR(rc);
diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
- rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
- if (IS_ERR(rc))
- return PTR_ERR(rc);
- return 0;
+ rc = hypfs_create_str(cpu_dir, "type", buffer);
+ return PTR_RET(rc);
}
-static void *hypfs_create_phys_files(struct super_block *sb,
- struct dentry *parent_dir, void *phys_hdr)
+static void *hypfs_create_phys_files(struct dentry *parent_dir, void *phys_hdr)
{
int i;
void *cpu_info;
struct dentry *cpus_dir;
- cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");
+ cpus_dir = hypfs_mkdir(parent_dir, "cpus");
if (IS_ERR(cpus_dir))
return cpus_dir;
cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
int rc;
- rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
+ rc = hypfs_create_phys_cpu_files(cpus_dir, cpu_info);
if (rc)
return ERR_PTR(rc);
cpu_info += phys_cpu__size(diag204_info_type);
@@ -772,7 +720,7 @@ static void *hypfs_create_phys_files(struct super_block *sb,
return cpu_info;
}
-int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
+int hypfs_diag_create_files(struct dentry *root)
{
struct dentry *systems_dir, *hyp_dir;
void *time_hdr, *part_hdr;
@@ -783,7 +731,7 @@ int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
if (IS_ERR(buffer))
return PTR_ERR(buffer);
- systems_dir = hypfs_mkdir(sb, root, "systems");
+ systems_dir = hypfs_mkdir(root, "systems");
if (IS_ERR(systems_dir)) {
rc = PTR_ERR(systems_dir);
goto err_out;
@@ -791,25 +739,25 @@ int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
time_hdr = (struct x_info_blk_hdr *)buffer;
part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
- part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
+ part_hdr = hypfs_create_lpar_files(systems_dir, part_hdr);
if (IS_ERR(part_hdr)) {
rc = PTR_ERR(part_hdr);
goto err_out;
}
}
if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {
- ptr = hypfs_create_phys_files(sb, root, part_hdr);
+ ptr = hypfs_create_phys_files(root, part_hdr);
if (IS_ERR(ptr)) {
rc = PTR_ERR(ptr);
goto err_out;
}
}
- hyp_dir = hypfs_mkdir(sb, root, "hyp");
+ hyp_dir = hypfs_mkdir(root, "hyp");
if (IS_ERR(hyp_dir)) {
rc = PTR_ERR(hyp_dir);
goto err_out;
}
- ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");
+ ptr = hypfs_create_str(hyp_dir, "type", "LPAR Hypervisor");
if (IS_ERR(ptr)) {
rc = PTR_ERR(ptr);
goto err_out;
diff --git a/arch/s390/hypfs/hypfs_sprp.c b/arch/s390/hypfs/hypfs_sprp.c
new file mode 100644
index 00000000000..f043c3c7e73
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_sprp.c
@@ -0,0 +1,141 @@
+/*
+ * Hypervisor filesystem for Linux on s390.
+ * Set Partition-Resource Parameter interface.
+ *
+ * Copyright IBM Corp. 2013
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <asm/compat.h>
+#include <asm/sclp.h>
+#include "hypfs.h"
+
+#define DIAG304_SET_WEIGHTS 0
+#define DIAG304_QUERY_PRP 1
+#define DIAG304_SET_CAPPING 2
+
+#define DIAG304_CMD_MAX 2
+
+static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
+{
+ register unsigned long _data asm("2") = (unsigned long) data;
+ register unsigned long _rc asm("3");
+ register unsigned long _cmd asm("4") = cmd;
+
+ asm volatile("diag %1,%2,0x304\n"
+ : "=d" (_rc) : "d" (_data), "d" (_cmd) : "memory");
+
+ return _rc;
+}
+
+static void hypfs_sprp_free(const void *data)
+{
+ free_page((unsigned long) data);
+}
+
+static int hypfs_sprp_create(void **data_ptr, void **free_ptr, size_t *size)
+{
+ unsigned long rc;
+ void *data;
+
+ data = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ rc = hypfs_sprp_diag304(data, DIAG304_QUERY_PRP);
+ if (rc != 1) {
+ *data_ptr = *free_ptr = NULL;
+ *size = 0;
+ free_page((unsigned long) data);
+ return -EIO;
+ }
+ *data_ptr = *free_ptr = data;
+ *size = PAGE_SIZE;
+ return 0;
+}
+
+static int __hypfs_sprp_ioctl(void __user *user_area)
+{
+ struct hypfs_diag304 diag304;
+ unsigned long cmd;
+ void __user *udata;
+ void *data;
+ int rc;
+
+ if (copy_from_user(&diag304, user_area, sizeof(diag304)))
+ return -EFAULT;
+ if ((diag304.args[0] >> 8) != 0 || diag304.args[1] > DIAG304_CMD_MAX)
+ return -EINVAL;
+
+ data = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!data)
+ return -ENOMEM;
+
+ udata = (void __user *)(unsigned long) diag304.data;
+ if (diag304.args[1] == DIAG304_SET_WEIGHTS ||
+ diag304.args[1] == DIAG304_SET_CAPPING)
+ if (copy_from_user(data, udata, PAGE_SIZE)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ cmd = *(unsigned long *) &diag304.args[0];
+ diag304.rc = hypfs_sprp_diag304(data, cmd);
+
+ if (diag304.args[1] == DIAG304_QUERY_PRP)
+ if (copy_to_user(udata, data, PAGE_SIZE)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ rc = copy_to_user(user_area, &diag304, sizeof(diag304)) ? -EFAULT : 0;
+out:
+ free_page((unsigned long) data);
+ return rc;
+}
+
+static long hypfs_sprp_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (is_compat_task())
+ argp = compat_ptr(arg);
+ else
+ argp = (void __user *) arg;
+ switch (cmd) {
+ case HYPFS_DIAG304:
+ return __hypfs_sprp_ioctl(argp);
+ default: /* unknown ioctl number */
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static struct hypfs_dbfs_file hypfs_sprp_file = {
+ .name = "diag_304",
+ .data_create = hypfs_sprp_create,
+ .data_free = hypfs_sprp_free,
+ .unlocked_ioctl = hypfs_sprp_ioctl,
+};
+
+int hypfs_sprp_init(void)
+{
+ if (!sclp_has_sprp())
+ return 0;
+ return hypfs_dbfs_create_file(&hypfs_sprp_file);
+}
+
+void hypfs_sprp_exit(void)
+{
+ if (!sclp_has_sprp())
+ return;
+ hypfs_dbfs_remove_file(&hypfs_sprp_file);
+}
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index 26cf177f6a3..32040ace00e 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -1,7 +1,7 @@
/*
* Hypervisor filesystem for Linux on s390. z/VM implementation.
*
- * Copyright (C) IBM Corp. 2006
+ * Copyright IBM Corp. 2006
* Author(s): Michael Holzheu <holzheu@de.ibm.com>
*/
@@ -20,8 +20,6 @@ static char local_guest[] = " ";
static char all_guests[] = "* ";
static char *guest_query;
-static struct dentry *dbfs_d2fc_file;
-
struct diag2fc_data {
__u32 version;
__u32 flags;
@@ -34,7 +32,7 @@ struct diag2fc_data {
__u32 pcpus;
__u32 lcpus;
__u32 vcpus;
- __u32 cpu_min;
+ __u32 ocpus;
__u32 cpu_max;
__u32 cpu_shares;
__u32 cpu_use_samp;
@@ -104,21 +102,20 @@ static void *diag2fc_store(char *query, unsigned int *count, int offset)
return data;
}
-static void diag2fc_free(void *data)
+static void diag2fc_free(const void *data)
{
vfree(data);
}
-#define ATTRIBUTE(sb, dir, name, member) \
+#define ATTRIBUTE(dir, name, member) \
do { \
void *rc; \
- rc = hypfs_create_u64(sb, dir, name, member); \
+ rc = hypfs_create_u64(dir, name, member); \
if (IS_ERR(rc)) \
return PTR_ERR(rc); \
} while(0)
-static int hpyfs_vm_create_guest(struct super_block *sb,
- struct dentry *systems_dir,
+static int hpyfs_vm_create_guest(struct dentry *systems_dir,
struct diag2fc_data *data)
{
char guest_name[NAME_LEN + 1] = {};
@@ -132,46 +129,51 @@ static int hpyfs_vm_create_guest(struct super_block *sb,
memcpy(guest_name, data->guest_name, NAME_LEN);
EBCASC(guest_name, NAME_LEN);
strim(guest_name);
- guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
+ guest_dir = hypfs_mkdir(systems_dir, guest_name);
if (IS_ERR(guest_dir))
return PTR_ERR(guest_dir);
- ATTRIBUTE(sb, guest_dir, "onlinetime_us", data->el_time);
+ ATTRIBUTE(guest_dir, "onlinetime_us", data->el_time);
/* logical cpu information */
- cpus_dir = hypfs_mkdir(sb, guest_dir, "cpus");
+ cpus_dir = hypfs_mkdir(guest_dir, "cpus");
if (IS_ERR(cpus_dir))
return PTR_ERR(cpus_dir);
- ATTRIBUTE(sb, cpus_dir, "cputime_us", data->used_cpu);
- ATTRIBUTE(sb, cpus_dir, "capped", capped_value);
- ATTRIBUTE(sb, cpus_dir, "dedicated", dedicated_flag);
- ATTRIBUTE(sb, cpus_dir, "count", data->vcpus);
- ATTRIBUTE(sb, cpus_dir, "weight_min", data->cpu_min);
- ATTRIBUTE(sb, cpus_dir, "weight_max", data->cpu_max);
- ATTRIBUTE(sb, cpus_dir, "weight_cur", data->cpu_shares);
+ ATTRIBUTE(cpus_dir, "cputime_us", data->used_cpu);
+ ATTRIBUTE(cpus_dir, "capped", capped_value);
+ ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag);
+ ATTRIBUTE(cpus_dir, "count", data->vcpus);
+ /*
+ * Note: The "weight_min" attribute got the wrong name.
+ * The value represents the number of non-stopped (operating)
+ * CPUS.
+ */
+ ATTRIBUTE(cpus_dir, "weight_min", data->ocpus);
+ ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max);
+ ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares);
/* memory information */
- mem_dir = hypfs_mkdir(sb, guest_dir, "mem");
+ mem_dir = hypfs_mkdir(guest_dir, "mem");
if (IS_ERR(mem_dir))
return PTR_ERR(mem_dir);
- ATTRIBUTE(sb, mem_dir, "min_KiB", data->mem_min_kb);
- ATTRIBUTE(sb, mem_dir, "max_KiB", data->mem_max_kb);
- ATTRIBUTE(sb, mem_dir, "used_KiB", data->mem_used_kb);
- ATTRIBUTE(sb, mem_dir, "share_KiB", data->mem_share_kb);
+ ATTRIBUTE(mem_dir, "min_KiB", data->mem_min_kb);
+ ATTRIBUTE(mem_dir, "max_KiB", data->mem_max_kb);
+ ATTRIBUTE(mem_dir, "used_KiB", data->mem_used_kb);
+ ATTRIBUTE(mem_dir, "share_KiB", data->mem_share_kb);
/* samples */
- samples_dir = hypfs_mkdir(sb, guest_dir, "samples");
+ samples_dir = hypfs_mkdir(guest_dir, "samples");
if (IS_ERR(samples_dir))
return PTR_ERR(samples_dir);
- ATTRIBUTE(sb, samples_dir, "cpu_using", data->cpu_use_samp);
- ATTRIBUTE(sb, samples_dir, "cpu_delay", data->cpu_delay_samp);
- ATTRIBUTE(sb, samples_dir, "mem_delay", data->page_wait_samp);
- ATTRIBUTE(sb, samples_dir, "idle", data->idle_samp);
- ATTRIBUTE(sb, samples_dir, "other", data->other_samp);
- ATTRIBUTE(sb, samples_dir, "total", data->total_samp);
+ ATTRIBUTE(samples_dir, "cpu_using", data->cpu_use_samp);
+ ATTRIBUTE(samples_dir, "cpu_delay", data->cpu_delay_samp);
+ ATTRIBUTE(samples_dir, "mem_delay", data->page_wait_samp);
+ ATTRIBUTE(samples_dir, "idle", data->idle_samp);
+ ATTRIBUTE(samples_dir, "other", data->other_samp);
+ ATTRIBUTE(samples_dir, "total", data->total_samp);
return 0;
}
-int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
+int hypfs_vm_create_files(struct dentry *root)
{
struct dentry *dir, *file;
struct diag2fc_data *data;
@@ -183,38 +185,38 @@ int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
return PTR_ERR(data);
/* Hpervisor Info */
- dir = hypfs_mkdir(sb, root, "hyp");
+ dir = hypfs_mkdir(root, "hyp");
if (IS_ERR(dir)) {
rc = PTR_ERR(dir);
goto failed;
}
- file = hypfs_create_str(sb, dir, "type", "z/VM Hypervisor");
+ file = hypfs_create_str(dir, "type", "z/VM Hypervisor");
if (IS_ERR(file)) {
rc = PTR_ERR(file);
goto failed;
}
/* physical cpus */
- dir = hypfs_mkdir(sb, root, "cpus");
+ dir = hypfs_mkdir(root, "cpus");
if (IS_ERR(dir)) {
rc = PTR_ERR(dir);
goto failed;
}
- file = hypfs_create_u64(sb, dir, "count", data->lcpus);
+ file = hypfs_create_u64(dir, "count", data->lcpus);
if (IS_ERR(file)) {
rc = PTR_ERR(file);
goto failed;
}
/* guests */
- dir = hypfs_mkdir(sb, root, "systems");
+ dir = hypfs_mkdir(root, "systems");
if (IS_ERR(dir)) {
rc = PTR_ERR(dir);
goto failed;
}
for (i = 0; i < count; i++) {
- rc = hpyfs_vm_create_guest(sb, dir, &(data[i]));
+ rc = hpyfs_vm_create_guest(dir, &(data[i]));
if (rc)
goto failed;
}
@@ -239,43 +241,29 @@ struct dbfs_d2fc {
char buf[]; /* d2fc buffer */
} __attribute__ ((packed));
-static int dbfs_d2fc_open(struct inode *inode, struct file *file)
+static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size)
{
- struct dbfs_d2fc *data;
+ struct dbfs_d2fc *d2fc;
unsigned int count;
- data = diag2fc_store(guest_query, &count, sizeof(data->hdr));
- if (IS_ERR(data))
- return PTR_ERR(data);
- get_clock_ext(data->hdr.tod_ext);
- data->hdr.len = count * sizeof(struct diag2fc_data);
- data->hdr.version = DBFS_D2FC_HDR_VERSION;
- data->hdr.count = count;
- memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved));
- file->private_data = data;
- return nonseekable_open(inode, file);
-}
-
-static int dbfs_d2fc_release(struct inode *inode, struct file *file)
-{
- diag2fc_free(file->private_data);
+ d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr));
+ if (IS_ERR(d2fc))
+ return PTR_ERR(d2fc);
+ get_tod_clock_ext(d2fc->hdr.tod_ext);
+ d2fc->hdr.len = count * sizeof(struct diag2fc_data);
+ d2fc->hdr.version = DBFS_D2FC_HDR_VERSION;
+ d2fc->hdr.count = count;
+ memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved));
+ *data = d2fc;
+ *data_free_ptr = d2fc;
+ *size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr);
return 0;
}
-static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf,
- size_t size, loff_t *ppos)
-{
- struct dbfs_d2fc *data = file->private_data;
-
- return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len +
- sizeof(struct dbfs_d2fc_hdr));
-}
-
-static const struct file_operations dbfs_d2fc_ops = {
- .open = dbfs_d2fc_open,
- .read = dbfs_d2fc_read,
- .release = dbfs_d2fc_release,
- .llseek = no_llseek,
+static struct hypfs_dbfs_file dbfs_file_2fc = {
+ .name = "diag_2fc",
+ .data_create = dbfs_diag2fc_create,
+ .data_free = diag2fc_free,
};
int hypfs_vm_init(void)
@@ -288,18 +276,12 @@ int hypfs_vm_init(void)
guest_query = local_guest;
else
return -EACCES;
-
- dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir,
- NULL, &dbfs_d2fc_ops);
- if (IS_ERR(dbfs_d2fc_file))
- return PTR_ERR(dbfs_d2fc_file);
-
- return 0;
+ return hypfs_dbfs_create_file(&dbfs_file_2fc);
}
void hypfs_vm_exit(void)
{
if (!MACHINE_IS_VM)
return;
- debugfs_remove(dbfs_d2fc_file);
+ hypfs_dbfs_remove_file(&dbfs_file_2fc);
}
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 47cc446dab8..c952b981e4f 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -1,5 +1,4 @@
/*
- * arch/s390/hypfs/inode.c
* Hypervisor filesystem for Linux on s390.
*
* Copyright IBM Corp. 2006, 2008
@@ -22,18 +21,18 @@
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
+#include <linux/aio.h>
#include <asm/ebcdic.h>
#include "hypfs.h"
#define HYPFS_MAGIC 0x687970 /* ASCII 'hyp' */
#define TMP_SIZE 64 /* size of temporary buffers */
-static struct dentry *hypfs_create_update_file(struct super_block *sb,
- struct dentry *dir);
+static struct dentry *hypfs_create_update_file(struct dentry *dir);
struct hypfs_sb_info {
- uid_t uid; /* uid used for files and dirs */
- gid_t gid; /* gid used for files and dirs */
+ kuid_t uid; /* uid used for files and dirs */
+ kgid_t gid; /* gid used for files and dirs */
struct dentry *update_file; /* file to trigger update */
time_t last_update; /* last update time in secs since 1970 */
struct mutex lock; /* lock to protect update process */
@@ -46,8 +45,6 @@ static const struct super_operations hypfs_s_ops;
/* start of list of all dentries, which have to be deleted on update */
static struct dentry *hypfs_last_dentry;
-struct dentry *hypfs_dbfs_dir;
-
static void hypfs_update_update(struct super_block *sb)
{
struct hypfs_sb_info *sb_info = sb->s_fs_info;
@@ -75,8 +72,6 @@ static void hypfs_remove(struct dentry *dentry)
struct dentry *parent;
parent = dentry->d_parent;
- if (!parent || !parent->d_inode)
- return;
mutex_lock(&parent->d_inode->i_mutex);
if (hypfs_positive(dentry)) {
if (S_ISDIR(dentry->d_inode->i_mode))
@@ -99,33 +94,32 @@ static void hypfs_delete_tree(struct dentry *root)
}
}
-static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+static struct inode *hypfs_make_inode(struct super_block *sb, umode_t mode)
{
struct inode *ret = new_inode(sb);
if (ret) {
struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+ ret->i_ino = get_next_ino();
ret->i_mode = mode;
ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
- if (mode & S_IFDIR)
- ret->i_nlink = 2;
- else
- ret->i_nlink = 1;
+ if (S_ISDIR(mode))
+ set_nlink(ret, 2);
}
return ret;
}
static void hypfs_evict_inode(struct inode *inode)
{
- end_writeback(inode);
+ clear_inode(inode);
kfree(inode->i_private);
}
static int hypfs_open(struct inode *inode, struct file *filp)
{
- char *data = filp->f_path.dentry->d_inode->i_private;
+ char *data = file_inode(filp)->i_private;
struct hypfs_sb_info *fs_info;
if (filp->f_mode & FMODE_WRITE) {
@@ -177,12 +171,10 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t offset)
{
int rc;
- struct super_block *sb;
- struct hypfs_sb_info *fs_info;
+ struct super_block *sb = file_inode(iocb->ki_filp)->i_sb;
+ struct hypfs_sb_info *fs_info = sb->s_fs_info;
size_t count = iov_length(iov, nr_segs);
- sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb;
- fs_info = sb->s_fs_info;
/*
* Currently we only allow one update per second for two reasons:
* 1. diag 204 is VERY expensive
@@ -200,9 +192,9 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
}
hypfs_delete_tree(sb->s_root);
if (MACHINE_IS_VM)
- rc = hypfs_vm_create_files(sb, sb->s_root);
+ rc = hypfs_vm_create_files(sb->s_root);
else
- rc = hypfs_diag_create_files(sb, sb->s_root);
+ rc = hypfs_diag_create_files(sb->s_root);
if (rc) {
pr_err("Updating the hypfs tree failed\n");
hypfs_delete_tree(sb->s_root);
@@ -233,6 +225,8 @@ static int hypfs_parse_options(char *options, struct super_block *sb)
{
char *str;
substring_t args[MAX_OPT_ARGS];
+ kuid_t uid;
+ kgid_t gid;
if (!options)
return 0;
@@ -247,12 +241,18 @@ static int hypfs_parse_options(char *options, struct super_block *sb)
case opt_uid:
if (match_int(&args[0], &option))
return -EINVAL;
- hypfs_info->uid = option;
+ uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(uid))
+ return -EINVAL;
+ hypfs_info->uid = uid;
break;
case opt_gid:
if (match_int(&args[0], &option))
return -EINVAL;
- hypfs_info->gid = option;
+ gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(gid))
+ return -EINVAL;
+ hypfs_info->gid = gid;
break;
case opt_err:
default:
@@ -263,12 +263,12 @@ static int hypfs_parse_options(char *options, struct super_block *sb)
return 0;
}
-static int hypfs_show_options(struct seq_file *s, struct vfsmount *mnt)
+static int hypfs_show_options(struct seq_file *s, struct dentry *root)
{
- struct hypfs_sb_info *hypfs_info = mnt->mnt_sb->s_fs_info;
+ struct hypfs_sb_info *hypfs_info = root->d_sb->s_fs_info;
- seq_printf(s, ",uid=%u", hypfs_info->uid);
- seq_printf(s, ",gid=%u", hypfs_info->gid);
+ seq_printf(s, ",uid=%u", from_kuid_munged(&init_user_ns, hypfs_info->uid));
+ seq_printf(s, ",gid=%u", from_kgid_munged(&init_user_ns, hypfs_info->gid));
return 0;
}
@@ -297,18 +297,16 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
return -ENOMEM;
root_inode->i_op = &simple_dir_inode_operations;
root_inode->i_fop = &simple_dir_operations;
- sb->s_root = root_dentry = d_alloc_root(root_inode);
- if (!root_dentry) {
- iput(root_inode);
+ sb->s_root = root_dentry = d_make_root(root_inode);
+ if (!root_dentry)
return -ENOMEM;
- }
if (MACHINE_IS_VM)
- rc = hypfs_vm_create_files(sb, root_dentry);
+ rc = hypfs_vm_create_files(root_dentry);
else
- rc = hypfs_diag_create_files(sb, root_dentry);
+ rc = hypfs_diag_create_files(root_dentry);
if (rc)
return rc;
- sbi->update_file = hypfs_create_update_file(sb, root_dentry);
+ sbi->update_file = hypfs_create_update_file(root_dentry);
if (IS_ERR(sbi->update_file))
return PTR_ERR(sbi->update_file);
hypfs_update_update(sb);
@@ -335,9 +333,8 @@ static void hypfs_kill_super(struct super_block *sb)
kill_litter_super(sb);
}
-static struct dentry *hypfs_create_file(struct super_block *sb,
- struct dentry *parent, const char *name,
- char *data, mode_t mode)
+static struct dentry *hypfs_create_file(struct dentry *parent, const char *name,
+ char *data, umode_t mode)
{
struct dentry *dentry;
struct inode *inode;
@@ -348,22 +345,22 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
dentry = ERR_PTR(-ENOMEM);
goto fail;
}
- inode = hypfs_make_inode(sb, mode);
+ inode = hypfs_make_inode(parent->d_sb, mode);
if (!inode) {
dput(dentry);
dentry = ERR_PTR(-ENOMEM);
goto fail;
}
- if (mode & S_IFREG) {
+ if (S_ISREG(mode)) {
inode->i_fop = &hypfs_file_ops;
if (data)
inode->i_size = strlen(data);
else
inode->i_size = 0;
- } else if (mode & S_IFDIR) {
+ } else if (S_ISDIR(mode)) {
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- parent->d_inode->i_nlink++;
+ inc_nlink(parent->d_inode);
} else
BUG();
inode->i_private = data;
@@ -374,24 +371,22 @@ fail:
return dentry;
}
-struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
- const char *name)
+struct dentry *hypfs_mkdir(struct dentry *parent, const char *name)
{
struct dentry *dentry;
- dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE);
+ dentry = hypfs_create_file(parent, name, NULL, S_IFDIR | DIR_MODE);
if (IS_ERR(dentry))
return dentry;
hypfs_add_dentry(dentry);
return dentry;
}
-static struct dentry *hypfs_create_update_file(struct super_block *sb,
- struct dentry *dir)
+static struct dentry *hypfs_create_update_file(struct dentry *dir)
{
struct dentry *dentry;
- dentry = hypfs_create_file(sb, dir, "update", NULL,
+ dentry = hypfs_create_file(dir, "update", NULL,
S_IFREG | UPDATE_FILE_MODE);
/*
* We do not put the update file on the 'delete' list with
@@ -401,7 +396,7 @@ static struct dentry *hypfs_create_update_file(struct super_block *sb,
return dentry;
}
-struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
+struct dentry *hypfs_create_u64(struct dentry *dir,
const char *name, __u64 value)
{
char *buffer;
@@ -413,7 +408,7 @@ struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
if (!buffer)
return ERR_PTR(-ENOMEM);
dentry =
- hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+ hypfs_create_file(dir, name, buffer, S_IFREG | REG_FILE_MODE);
if (IS_ERR(dentry)) {
kfree(buffer);
return ERR_PTR(-ENOMEM);
@@ -422,7 +417,7 @@ struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
return dentry;
}
-struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir,
+struct dentry *hypfs_create_str(struct dentry *dir,
const char *name, char *string)
{
char *buffer;
@@ -433,7 +428,7 @@ struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir,
return ERR_PTR(-ENOMEM);
sprintf(buffer, "%s\n", string);
dentry =
- hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+ hypfs_create_file(dir, name, buffer, S_IFREG | REG_FILE_MODE);
if (IS_ERR(dentry)) {
kfree(buffer);
return ERR_PTR(-ENOMEM);
@@ -458,6 +453,7 @@ static struct file_system_type hypfs_type = {
.mount = hypfs_mount,
.kill_sb = hypfs_kill_super
};
+MODULE_ALIAS_FS("s390_hypfs");
static const struct super_operations hypfs_s_ops = {
.statfs = simple_statfs,
@@ -471,22 +467,25 @@ static int __init hypfs_init(void)
{
int rc;
- hypfs_dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
- if (IS_ERR(hypfs_dbfs_dir))
- return PTR_ERR(hypfs_dbfs_dir);
-
+ rc = hypfs_dbfs_init();
+ if (rc)
+ return rc;
if (hypfs_diag_init()) {
rc = -ENODATA;
- goto fail_debugfs_remove;
+ goto fail_dbfs_exit;
}
if (hypfs_vm_init()) {
rc = -ENODATA;
goto fail_hypfs_diag_exit;
}
+ if (hypfs_sprp_init()) {
+ rc = -ENODATA;
+ goto fail_hypfs_vm_exit;
+ }
s390_kobj = kobject_create_and_add("s390", hypervisor_kobj);
if (!s390_kobj) {
rc = -ENOMEM;
- goto fail_hypfs_vm_exit;
+ goto fail_hypfs_sprp_exit;
}
rc = register_filesystem(&hypfs_type);
if (rc)
@@ -495,24 +494,26 @@ static int __init hypfs_init(void)
fail_filesystem:
kobject_put(s390_kobj);
+fail_hypfs_sprp_exit:
+ hypfs_sprp_exit();
fail_hypfs_vm_exit:
hypfs_vm_exit();
fail_hypfs_diag_exit:
hypfs_diag_exit();
-fail_debugfs_remove:
- debugfs_remove(hypfs_dbfs_dir);
-
+fail_dbfs_exit:
+ hypfs_dbfs_exit();
pr_err("Initialization of hypfs failed with rc=%i\n", rc);
return rc;
}
static void __exit hypfs_exit(void)
{
- hypfs_diag_exit();
- hypfs_vm_exit();
- debugfs_remove(hypfs_dbfs_dir);
unregister_filesystem(&hypfs_type);
kobject_put(s390_kobj);
+ hypfs_sprp_exit();
+ hypfs_vm_exit();
+ hypfs_diag_exit();
+ hypfs_dbfs_exit();
}
module_init(hypfs_init)