18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Hypervisor filesystem for Linux on s390 - debugfs interface 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2010 68c2ecf20Sopenharmony_ci * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include "hypfs.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic struct dentry *dbfs_dir; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci struct hypfs_dbfs_data *data; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci data = kmalloc(sizeof(*data), GFP_KERNEL); 198c2ecf20Sopenharmony_ci if (!data) 208c2ecf20Sopenharmony_ci return NULL; 218c2ecf20Sopenharmony_ci data->dbfs_file = f; 228c2ecf20Sopenharmony_ci return data; 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void hypfs_dbfs_data_free(struct hypfs_dbfs_data *data) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci data->dbfs_file->data_free(data->buf_free_ptr); 288c2ecf20Sopenharmony_ci kfree(data); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic ssize_t dbfs_read(struct file *file, char __user *buf, 328c2ecf20Sopenharmony_ci size_t size, loff_t *ppos) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct hypfs_dbfs_data *data; 358c2ecf20Sopenharmony_ci struct hypfs_dbfs_file *df; 368c2ecf20Sopenharmony_ci ssize_t rc; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci if (*ppos != 0) 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci df = file_inode(file)->i_private; 428c2ecf20Sopenharmony_ci mutex_lock(&df->lock); 438c2ecf20Sopenharmony_ci data = hypfs_dbfs_data_alloc(df); 448c2ecf20Sopenharmony_ci if (!data) { 458c2ecf20Sopenharmony_ci mutex_unlock(&df->lock); 468c2ecf20Sopenharmony_ci return -ENOMEM; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci rc = df->data_create(&data->buf, &data->buf_free_ptr, &data->size); 498c2ecf20Sopenharmony_ci if (rc) { 508c2ecf20Sopenharmony_ci mutex_unlock(&df->lock); 518c2ecf20Sopenharmony_ci kfree(data); 528c2ecf20Sopenharmony_ci return rc; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci mutex_unlock(&df->lock); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); 578c2ecf20Sopenharmony_ci hypfs_dbfs_data_free(data); 588c2ecf20Sopenharmony_ci return rc; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct hypfs_dbfs_file *df = file_inode(file)->i_private; 648c2ecf20Sopenharmony_ci long rc; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci mutex_lock(&df->lock); 678c2ecf20Sopenharmony_ci if (df->unlocked_ioctl) 688c2ecf20Sopenharmony_ci rc = df->unlocked_ioctl(file, cmd, arg); 698c2ecf20Sopenharmony_ci else 708c2ecf20Sopenharmony_ci rc = -ENOTTY; 718c2ecf20Sopenharmony_ci mutex_unlock(&df->lock); 728c2ecf20Sopenharmony_ci return rc; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic const struct file_operations dbfs_ops = { 768c2ecf20Sopenharmony_ci .read = dbfs_read, 778c2ecf20Sopenharmony_ci .llseek = no_llseek, 788c2ecf20Sopenharmony_ci .unlocked_ioctl = dbfs_ioctl, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_civoid hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, 848c2ecf20Sopenharmony_ci &dbfs_ops); 858c2ecf20Sopenharmony_ci mutex_init(&df->lock); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_civoid hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci debugfs_remove(df->dentry); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_civoid hypfs_dbfs_init(void) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_civoid hypfs_dbfs_exit(void) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci debugfs_remove(dbfs_dir); 1018c2ecf20Sopenharmony_ci} 102