forked from Minki/linux
a53c8fab3f
Remove the file name from the comment at top of many files. In most cases the file name was wrong anyway, so it's rather pointless. Also unify the IBM copyright statement. We did have a lot of sightly different statements and wanted to change them one after another whenever a file gets touched. However that never happened. Instead people start to take the old/"wrong" statements to use as a template for new files. So unify all of them in one go. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
117 lines
2.5 KiB
C
117 lines
2.5 KiB
C
/*
|
|
* 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->f_path.dentry->d_inode->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 const struct file_operations dbfs_ops = {
|
|
.read = dbfs_read,
|
|
.llseek = no_llseek,
|
|
};
|
|
|
|
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);
|
|
if (IS_ERR(dbfs_dir))
|
|
return PTR_ERR(dbfs_dir);
|
|
return 0;
|
|
}
|
|
|
|
void hypfs_dbfs_exit(void)
|
|
{
|
|
debugfs_remove(dbfs_dir);
|
|
}
|