linux/arch/s390/hypfs/hypfs_dbfs.c
Heiko Carstens 3325b4d857 s390/hypfs: factor out filesystem code
The s390_hypfs filesystem is deprecated and shouldn't be used due to its
rather odd semantics. It creates a whole directory structure with static
file contents so a user can read a consistent state while within that
directory.
Writing to its update attribute will remove and rebuild nearly the whole
filesystem, so that again a user can read a consistent state, even if
multiple files need to be read.

Given that this wastes a lot of CPU cycles, and involves a lot of code,
binary interfaces have been added quite a couple of years ago, which simply
pass the binary data to user space, and let user space decode the data.
This is the preferred and only way how the data should be retrieved.

The assumption is that there are no users of the s390_hypfs filesystem.
However instead of just removing the code, and having to revert in case
there are actually users, factor the filesystem code out and make it only
available via a new config option.

This config option is supposed to be disabled. If it turns out there are no
complaints the filesystem code can be removed probably in a couple of
years.

Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
2023-07-24 12:12:22 +02:00

123 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* 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;
data->dbfs_file = f;
return data;
}
static void hypfs_dbfs_data_free(struct hypfs_dbfs_data *data)
{
data->dbfs_file->data_free(data->buf_free_ptr);
kfree(data);
}
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);
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;
}
mutex_unlock(&df->lock);
rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
hypfs_dbfs_data_free(data);
return rc;
}
static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct hypfs_dbfs_file *df = file_inode(file)->i_private;
long rc;
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,
};
void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
{
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
&dbfs_ops);
mutex_init(&df->lock);
}
void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
{
debugfs_remove(df->dentry);
}
static int __init hypfs_dbfs_init(void)
{
int rc = -ENODATA;
dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
if (hypfs_diag_init())
goto fail_dbfs_exit;
if (hypfs_vm_init())
goto fail_hypfs_diag_exit;
hypfs_sprp_init();
if (hypfs_diag0c_init())
goto fail_hypfs_sprp_exit;
rc = hypfs_fs_init();
if (rc)
goto fail_hypfs_diag0c_exit;
return 0;
fail_hypfs_diag0c_exit:
hypfs_diag0c_exit();
fail_hypfs_sprp_exit:
hypfs_sprp_exit();
hypfs_vm_exit();
fail_hypfs_diag_exit:
hypfs_diag_exit();
pr_err("Initialization of hypfs failed with rc=%i\n", rc);
fail_dbfs_exit:
debugfs_remove(dbfs_dir);
return rc;
}
device_initcall(hypfs_dbfs_init)