hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// 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);
}
 
void hypfs_dbfs_init(void)
{
   dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
}
 
void hypfs_dbfs_exit(void)
{
   debugfs_remove(dbfs_dir);
}