Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Hypervisor filesystem for Linux on s390 - debugfs interface |
| 3 | * |
Heiko Carstens | a53c8fa | 2012-07-20 11:15:04 +0200 | [diff] [blame] | 4 | * Copyright IBM Corp. 2010 |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 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; |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 20 | data->dbfs_file = f; |
| 21 | return data; |
| 22 | } |
| 23 | |
Michael Holzheu | a178220 | 2015-02-09 14:49:32 +0100 | [diff] [blame] | 24 | static void hypfs_dbfs_data_free(struct hypfs_dbfs_data *data) |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 25 | { |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 26 | data->dbfs_file->data_free(data->buf_free_ptr); |
| 27 | kfree(data); |
| 28 | } |
| 29 | |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 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 | |
Al Viro | 496ad9a | 2013-01-23 17:07:38 -0500 | [diff] [blame] | 40 | df = file_inode(file)->i_private; |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 41 | mutex_lock(&df->lock); |
Michael Holzheu | a178220 | 2015-02-09 14:49:32 +0100 | [diff] [blame] | 42 | data = hypfs_dbfs_data_alloc(df); |
| 43 | if (!data) { |
| 44 | mutex_unlock(&df->lock); |
| 45 | return -ENOMEM; |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 46 | } |
Michael Holzheu | a178220 | 2015-02-09 14:49:32 +0100 | [diff] [blame] | 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; |
| 52 | } |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 53 | mutex_unlock(&df->lock); |
| 54 | |
| 55 | rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); |
Michael Holzheu | a178220 | 2015-02-09 14:49:32 +0100 | [diff] [blame] | 56 | hypfs_dbfs_data_free(data); |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 57 | return rc; |
| 58 | } |
| 59 | |
Martin Schwidefsky | 07be038 | 2014-01-24 09:18:52 +0100 | [diff] [blame] | 60 | static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 61 | { |
Al Viro | a455589 | 2014-10-21 20:11:25 -0400 | [diff] [blame] | 62 | struct hypfs_dbfs_file *df = file_inode(file)->i_private; |
Martin Schwidefsky | 07be038 | 2014-01-24 09:18:52 +0100 | [diff] [blame] | 63 | long rc; |
| 64 | |
Martin Schwidefsky | 07be038 | 2014-01-24 09:18:52 +0100 | [diff] [blame] | 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 | |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 74 | static const struct file_operations dbfs_ops = { |
| 75 | .read = dbfs_read, |
| 76 | .llseek = no_llseek, |
Martin Schwidefsky | 07be038 | 2014-01-24 09:18:52 +0100 | [diff] [blame] | 77 | .unlocked_ioctl = dbfs_ioctl, |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 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); |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 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); |
Rusty Russell | 8c6ffba | 2013-07-15 11:20:32 +0930 | [diff] [blame] | 98 | return PTR_ERR_OR_ZERO(dbfs_dir); |
Michael Holzheu | 2fcb368 | 2011-01-05 12:47:43 +0100 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | void hypfs_dbfs_exit(void) |
| 102 | { |
| 103 | debugfs_remove(dbfs_dir); |
| 104 | } |