1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Hypervisor filesystem for Linux on s390 - debugfs interface
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright IBM Corp. 2010
6*4882a593Smuzhiyun * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include "hypfs.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun static struct dentry *dbfs_dir;
13*4882a593Smuzhiyun
hypfs_dbfs_data_alloc(struct hypfs_dbfs_file * f)14*4882a593Smuzhiyun static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun struct hypfs_dbfs_data *data;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun data = kmalloc(sizeof(*data), GFP_KERNEL);
19*4882a593Smuzhiyun if (!data)
20*4882a593Smuzhiyun return NULL;
21*4882a593Smuzhiyun data->dbfs_file = f;
22*4882a593Smuzhiyun return data;
23*4882a593Smuzhiyun }
24*4882a593Smuzhiyun
hypfs_dbfs_data_free(struct hypfs_dbfs_data * data)25*4882a593Smuzhiyun static void hypfs_dbfs_data_free(struct hypfs_dbfs_data *data)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun data->dbfs_file->data_free(data->buf_free_ptr);
28*4882a593Smuzhiyun kfree(data);
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
dbfs_read(struct file * file,char __user * buf,size_t size,loff_t * ppos)31*4882a593Smuzhiyun static ssize_t dbfs_read(struct file *file, char __user *buf,
32*4882a593Smuzhiyun size_t size, loff_t *ppos)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun struct hypfs_dbfs_data *data;
35*4882a593Smuzhiyun struct hypfs_dbfs_file *df;
36*4882a593Smuzhiyun ssize_t rc;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun if (*ppos != 0)
39*4882a593Smuzhiyun return 0;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun df = file_inode(file)->i_private;
42*4882a593Smuzhiyun mutex_lock(&df->lock);
43*4882a593Smuzhiyun data = hypfs_dbfs_data_alloc(df);
44*4882a593Smuzhiyun if (!data) {
45*4882a593Smuzhiyun mutex_unlock(&df->lock);
46*4882a593Smuzhiyun return -ENOMEM;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun rc = df->data_create(&data->buf, &data->buf_free_ptr, &data->size);
49*4882a593Smuzhiyun if (rc) {
50*4882a593Smuzhiyun mutex_unlock(&df->lock);
51*4882a593Smuzhiyun kfree(data);
52*4882a593Smuzhiyun return rc;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun mutex_unlock(&df->lock);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
57*4882a593Smuzhiyun hypfs_dbfs_data_free(data);
58*4882a593Smuzhiyun return rc;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
dbfs_ioctl(struct file * file,unsigned int cmd,unsigned long arg)61*4882a593Smuzhiyun static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct hypfs_dbfs_file *df = file_inode(file)->i_private;
64*4882a593Smuzhiyun long rc;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun mutex_lock(&df->lock);
67*4882a593Smuzhiyun if (df->unlocked_ioctl)
68*4882a593Smuzhiyun rc = df->unlocked_ioctl(file, cmd, arg);
69*4882a593Smuzhiyun else
70*4882a593Smuzhiyun rc = -ENOTTY;
71*4882a593Smuzhiyun mutex_unlock(&df->lock);
72*4882a593Smuzhiyun return rc;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun static const struct file_operations dbfs_ops = {
76*4882a593Smuzhiyun .read = dbfs_read,
77*4882a593Smuzhiyun .llseek = no_llseek,
78*4882a593Smuzhiyun .unlocked_ioctl = dbfs_ioctl,
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun
hypfs_dbfs_create_file(struct hypfs_dbfs_file * df)81*4882a593Smuzhiyun void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
84*4882a593Smuzhiyun &dbfs_ops);
85*4882a593Smuzhiyun mutex_init(&df->lock);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
hypfs_dbfs_remove_file(struct hypfs_dbfs_file * df)88*4882a593Smuzhiyun void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun debugfs_remove(df->dentry);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
hypfs_dbfs_init(void)93*4882a593Smuzhiyun void hypfs_dbfs_init(void)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
hypfs_dbfs_exit(void)98*4882a593Smuzhiyun void hypfs_dbfs_exit(void)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun debugfs_remove(dbfs_dir);
101*4882a593Smuzhiyun }
102