Commit | Line | Data |
---|---|---|
2fcb3686 MH |
1 | /* |
2 | * Hypervisor filesystem for Linux on s390 - debugfs interface | |
3 | * | |
a53c8fab | 4 | * Copyright IBM Corp. 2010 |
2fcb3686 MH |
5 | * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> |
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; | |
2fcb3686 MH |
20 | data->dbfs_file = f; |
21 | return data; | |
22 | } | |
23 | ||
a178220d | 24 | static void hypfs_dbfs_data_free(struct hypfs_dbfs_data *data) |
2fcb3686 | 25 | { |
2fcb3686 MH |
26 | data->dbfs_file->data_free(data->buf_free_ptr); |
27 | kfree(data); | |
28 | } | |
29 | ||
2fcb3686 MH |
30 | static ssize_t dbfs_read(struct file *file, char __user *buf, |
31 | size_t size, loff_t *ppos) | |
32 | { | |
33 | struct hypfs_dbfs_data *data; | |
34 | struct hypfs_dbfs_file *df; | |
35 | ssize_t rc; | |
36 | ||
37 | if (*ppos != 0) | |
38 | return 0; | |
39 | ||
496ad9aa | 40 | df = file_inode(file)->i_private; |
2fcb3686 | 41 | mutex_lock(&df->lock); |
a178220d MH |
42 | data = hypfs_dbfs_data_alloc(df); |
43 | if (!data) { | |
44 | mutex_unlock(&df->lock); | |
45 | return -ENOMEM; | |
46 | } | |
47 | rc = df->data_create(&data->buf, &data->buf_free_ptr, &data->size); | |
48 | if (rc) { | |
49 | mutex_unlock(&df->lock); | |
50 | kfree(data); | |
51 | return rc; | |
2fcb3686 | 52 | } |
2fcb3686 MH |
53 | mutex_unlock(&df->lock); |
54 | ||
55 | rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); | |
a178220d | 56 | hypfs_dbfs_data_free(data); |
2fcb3686 MH |
57 | return rc; |
58 | } | |
59 | ||
07be0382 MS |
60 | static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
61 | { | |
a455589f | 62 | struct hypfs_dbfs_file *df = file_inode(file)->i_private; |
07be0382 MS |
63 | long rc; |
64 | ||
07be0382 MS |
65 | mutex_lock(&df->lock); |
66 | if (df->unlocked_ioctl) | |
67 | rc = df->unlocked_ioctl(file, cmd, arg); | |
68 | else | |
69 | rc = -ENOTTY; | |
70 | mutex_unlock(&df->lock); | |
71 | return rc; | |
72 | } | |
73 | ||
2fcb3686 MH |
74 | static const struct file_operations dbfs_ops = { |
75 | .read = dbfs_read, | |
76 | .llseek = no_llseek, | |
07be0382 | 77 | .unlocked_ioctl = dbfs_ioctl, |
2fcb3686 MH |
78 | }; |
79 | ||
80 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | |
81 | { | |
82 | df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, | |
83 | &dbfs_ops); | |
84 | if (IS_ERR(df->dentry)) | |
85 | return PTR_ERR(df->dentry); | |
86 | mutex_init(&df->lock); | |
2fcb3686 MH |
87 | return 0; |
88 | } | |
89 | ||
90 | void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) | |
91 | { | |
92 | debugfs_remove(df->dentry); | |
93 | } | |
94 | ||
95 | int hypfs_dbfs_init(void) | |
96 | { | |
97 | dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | |
8c6ffba0 | 98 | return PTR_ERR_OR_ZERO(dbfs_dir); |
2fcb3686 MH |
99 | } |
100 | ||
101 | void hypfs_dbfs_exit(void) | |
102 | { | |
103 | debugfs_remove(dbfs_dir); | |
104 | } |