aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/hypfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/hypfs/inode.c')
-rw-r--r--arch/s390/hypfs/inode.c129
1 files changed, 65 insertions, 64 deletions
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)