12fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu/* 22fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu * Hypervisor filesystem for Linux on s390 - debugfs interface 32fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu * 4a53c8fab3f87c995c30ac226a03af95361243144Heiko Carstens * Copyright IBM Corp. 2010 52fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> 62fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu */ 72fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 82fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu#include <linux/slab.h> 92fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu#include "hypfs.h" 102fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 112fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic struct dentry *dbfs_dir; 122fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 132fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) 142fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 152fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_data *data; 162fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 172fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data = kmalloc(sizeof(*data), GFP_KERNEL); 182fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (!data) 192fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return NULL; 202fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kref_init(&data->kref); 212fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data->dbfs_file = f; 222fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return data; 232fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 242fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 252fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic void hypfs_dbfs_data_free(struct kref *kref) 262fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 272fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_data *data; 282fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 292fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data = container_of(kref, struct hypfs_dbfs_data, kref); 302fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data->dbfs_file->data_free(data->buf_free_ptr); 312fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kfree(data); 322fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 332fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 342fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic void data_free_delayed(struct work_struct *work) 352fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 362fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_data *data; 372fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_file *df; 382fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 392fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu df = container_of(work, struct hypfs_dbfs_file, data_free_work.work); 402fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_lock(&df->lock); 412fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data = df->data; 422fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu df->data = NULL; 432fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_unlock(&df->lock); 442fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kref_put(&data->kref, hypfs_dbfs_data_free); 452fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 462fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 472fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic ssize_t dbfs_read(struct file *file, char __user *buf, 482fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu size_t size, loff_t *ppos) 492fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 502fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_data *data; 512fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu struct hypfs_dbfs_file *df; 522fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu ssize_t rc; 532fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 542fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (*ppos != 0) 552fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return 0; 562fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 57496ad9aa8ef448058e36ca7a787c61f2e63f0f54Al Viro df = file_inode(file)->i_private; 582fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_lock(&df->lock); 592fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (!df->data) { 602fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data = hypfs_dbfs_data_alloc(df); 612fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (!data) { 622fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_unlock(&df->lock); 632fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return -ENOMEM; 642fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu } 652fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu rc = df->data_create(&data->buf, &data->buf_free_ptr, 662fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu &data->size); 672fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (rc) { 682fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_unlock(&df->lock); 692fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kfree(data); 702fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return rc; 712fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu } 722fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu df->data = data; 732fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu schedule_delayed_work(&df->data_free_work, HZ); 742fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu } 752fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu data = df->data; 762fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kref_get(&data->kref); 772fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_unlock(&df->lock); 782fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 792fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); 802fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu kref_put(&data->kref, hypfs_dbfs_data_free); 812fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return rc; 822fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 832fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 8407be0382097027cde68d9268cc628741069b5762Martin Schwidefskystatic long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 8507be0382097027cde68d9268cc628741069b5762Martin Schwidefsky{ 8607be0382097027cde68d9268cc628741069b5762Martin Schwidefsky struct hypfs_dbfs_file *df; 8707be0382097027cde68d9268cc628741069b5762Martin Schwidefsky long rc; 8807be0382097027cde68d9268cc628741069b5762Martin Schwidefsky 8907be0382097027cde68d9268cc628741069b5762Martin Schwidefsky df = file->f_path.dentry->d_inode->i_private; 9007be0382097027cde68d9268cc628741069b5762Martin Schwidefsky mutex_lock(&df->lock); 9107be0382097027cde68d9268cc628741069b5762Martin Schwidefsky if (df->unlocked_ioctl) 9207be0382097027cde68d9268cc628741069b5762Martin Schwidefsky rc = df->unlocked_ioctl(file, cmd, arg); 9307be0382097027cde68d9268cc628741069b5762Martin Schwidefsky else 9407be0382097027cde68d9268cc628741069b5762Martin Schwidefsky rc = -ENOTTY; 9507be0382097027cde68d9268cc628741069b5762Martin Schwidefsky mutex_unlock(&df->lock); 9607be0382097027cde68d9268cc628741069b5762Martin Schwidefsky return rc; 9707be0382097027cde68d9268cc628741069b5762Martin Schwidefsky} 9807be0382097027cde68d9268cc628741069b5762Martin Schwidefsky 992fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheustatic const struct file_operations dbfs_ops = { 1002fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu .read = dbfs_read, 1012fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu .llseek = no_llseek, 10207be0382097027cde68d9268cc628741069b5762Martin Schwidefsky .unlocked_ioctl = dbfs_ioctl, 1032fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu}; 1042fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 1052fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheuint hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) 1062fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 1072fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, 1082fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu &dbfs_ops); 1092fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu if (IS_ERR(df->dentry)) 1102fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return PTR_ERR(df->dentry); 1112fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu mutex_init(&df->lock); 1122fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed); 1132fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu return 0; 1142fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 1152fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 1162fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheuvoid hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) 1172fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 1182fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu debugfs_remove(df->dentry); 1192fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 1202fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 1212fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheuint hypfs_dbfs_init(void) 1222fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 1232fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); 1248c6ffba0eddc8c110dbf444f51354ce42069abfcRusty Russell return PTR_ERR_OR_ZERO(dbfs_dir); 1252fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 1262fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu 1272fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheuvoid hypfs_dbfs_exit(void) 1282fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu{ 1292fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu debugfs_remove(dbfs_dir); 1302fcb3686e1601cff992e026dceeab1b22dc81178Michael Holzheu} 131