Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/s390/hypfs/hypfs_dbfs.c
10817 views
1
/*
2
* Hypervisor filesystem for Linux on s390 - debugfs interface
3
*
4
* Copyright (C) IBM Corp. 2010
5
* Author(s): Michael Holzheu <[email protected]>
6
*/
7
8
#include <linux/slab.h>
9
#include "hypfs.h"
10
11
static struct dentry *dbfs_dir;
12
13
static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f)
14
{
15
struct hypfs_dbfs_data *data;
16
17
data = kmalloc(sizeof(*data), GFP_KERNEL);
18
if (!data)
19
return NULL;
20
kref_init(&data->kref);
21
data->dbfs_file = f;
22
return data;
23
}
24
25
static void hypfs_dbfs_data_free(struct kref *kref)
26
{
27
struct hypfs_dbfs_data *data;
28
29
data = container_of(kref, struct hypfs_dbfs_data, kref);
30
data->dbfs_file->data_free(data->buf_free_ptr);
31
kfree(data);
32
}
33
34
static void data_free_delayed(struct work_struct *work)
35
{
36
struct hypfs_dbfs_data *data;
37
struct hypfs_dbfs_file *df;
38
39
df = container_of(work, struct hypfs_dbfs_file, data_free_work.work);
40
mutex_lock(&df->lock);
41
data = df->data;
42
df->data = NULL;
43
mutex_unlock(&df->lock);
44
kref_put(&data->kref, hypfs_dbfs_data_free);
45
}
46
47
static ssize_t dbfs_read(struct file *file, char __user *buf,
48
size_t size, loff_t *ppos)
49
{
50
struct hypfs_dbfs_data *data;
51
struct hypfs_dbfs_file *df;
52
ssize_t rc;
53
54
if (*ppos != 0)
55
return 0;
56
57
df = file->f_path.dentry->d_inode->i_private;
58
mutex_lock(&df->lock);
59
if (!df->data) {
60
data = hypfs_dbfs_data_alloc(df);
61
if (!data) {
62
mutex_unlock(&df->lock);
63
return -ENOMEM;
64
}
65
rc = df->data_create(&data->buf, &data->buf_free_ptr,
66
&data->size);
67
if (rc) {
68
mutex_unlock(&df->lock);
69
kfree(data);
70
return rc;
71
}
72
df->data = data;
73
schedule_delayed_work(&df->data_free_work, HZ);
74
}
75
data = df->data;
76
kref_get(&data->kref);
77
mutex_unlock(&df->lock);
78
79
rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
80
kref_put(&data->kref, hypfs_dbfs_data_free);
81
return rc;
82
}
83
84
static const struct file_operations dbfs_ops = {
85
.read = dbfs_read,
86
.llseek = no_llseek,
87
};
88
89
int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
90
{
91
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
92
&dbfs_ops);
93
if (IS_ERR(df->dentry))
94
return PTR_ERR(df->dentry);
95
mutex_init(&df->lock);
96
INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed);
97
return 0;
98
}
99
100
void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
101
{
102
debugfs_remove(df->dentry);
103
}
104
105
int hypfs_dbfs_init(void)
106
{
107
dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
108
if (IS_ERR(dbfs_dir))
109
return PTR_ERR(dbfs_dir);
110
return 0;
111
}
112
113
void hypfs_dbfs_exit(void)
114
{
115
debugfs_remove(dbfs_dir);
116
}
117
118