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