1*2fcb3686SMichael Holzheu /* 2*2fcb3686SMichael Holzheu * Hypervisor filesystem for Linux on s390 - debugfs interface 3*2fcb3686SMichael Holzheu * 4*2fcb3686SMichael Holzheu * Copyright (C) IBM Corp. 2010 5*2fcb3686SMichael Holzheu * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> 6*2fcb3686SMichael Holzheu */ 7*2fcb3686SMichael Holzheu 8*2fcb3686SMichael Holzheu #include <linux/slab.h> 9*2fcb3686SMichael Holzheu #include "hypfs.h" 10*2fcb3686SMichael Holzheu 11*2fcb3686SMichael Holzheu static struct dentry *dbfs_dir; 12*2fcb3686SMichael Holzheu 13*2fcb3686SMichael Holzheu static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) 14*2fcb3686SMichael Holzheu { 15*2fcb3686SMichael Holzheu struct hypfs_dbfs_data *data; 16*2fcb3686SMichael Holzheu 17*2fcb3686SMichael Holzheu data = kmalloc(sizeof(*data), GFP_KERNEL); 18*2fcb3686SMichael Holzheu if (!data) 19*2fcb3686SMichael Holzheu return NULL; 20*2fcb3686SMichael Holzheu kref_init(&data->kref); 21*2fcb3686SMichael Holzheu data->dbfs_file = f; 22*2fcb3686SMichael Holzheu return data; 23*2fcb3686SMichael Holzheu } 24*2fcb3686SMichael Holzheu 25*2fcb3686SMichael Holzheu static void hypfs_dbfs_data_free(struct kref *kref) 26*2fcb3686SMichael Holzheu { 27*2fcb3686SMichael Holzheu struct hypfs_dbfs_data *data; 28*2fcb3686SMichael Holzheu 29*2fcb3686SMichael Holzheu data = container_of(kref, struct hypfs_dbfs_data, kref); 30*2fcb3686SMichael Holzheu data->dbfs_file->data_free(data->buf_free_ptr); 31*2fcb3686SMichael Holzheu kfree(data); 32*2fcb3686SMichael Holzheu } 33*2fcb3686SMichael Holzheu 34*2fcb3686SMichael Holzheu static void data_free_delayed(struct work_struct *work) 35*2fcb3686SMichael Holzheu { 36*2fcb3686SMichael Holzheu struct hypfs_dbfs_data *data; 37*2fcb3686SMichael Holzheu struct hypfs_dbfs_file *df; 38*2fcb3686SMichael Holzheu 39*2fcb3686SMichael Holzheu df = container_of(work, struct hypfs_dbfs_file, data_free_work.work); 40*2fcb3686SMichael Holzheu mutex_lock(&df->lock); 41*2fcb3686SMichael Holzheu data = df->data; 42*2fcb3686SMichael Holzheu df->data = NULL; 43*2fcb3686SMichael Holzheu mutex_unlock(&df->lock); 44*2fcb3686SMichael Holzheu kref_put(&data->kref, hypfs_dbfs_data_free); 45*2fcb3686SMichael Holzheu } 46*2fcb3686SMichael Holzheu 47*2fcb3686SMichael Holzheu static ssize_t dbfs_read(struct file *file, char __user *buf, 48*2fcb3686SMichael Holzheu size_t size, loff_t *ppos) 49*2fcb3686SMichael Holzheu { 50*2fcb3686SMichael Holzheu struct hypfs_dbfs_data *data; 51*2fcb3686SMichael Holzheu struct hypfs_dbfs_file *df; 52*2fcb3686SMichael Holzheu ssize_t rc; 53*2fcb3686SMichael Holzheu 54*2fcb3686SMichael Holzheu if (*ppos != 0) 55*2fcb3686SMichael Holzheu return 0; 56*2fcb3686SMichael Holzheu 57*2fcb3686SMichael Holzheu df = file->f_path.dentry->d_inode->i_private; 58*2fcb3686SMichael Holzheu mutex_lock(&df->lock); 59*2fcb3686SMichael Holzheu if (!df->data) { 60*2fcb3686SMichael Holzheu data = hypfs_dbfs_data_alloc(df); 61*2fcb3686SMichael Holzheu if (!data) { 62*2fcb3686SMichael Holzheu mutex_unlock(&df->lock); 63*2fcb3686SMichael Holzheu return -ENOMEM; 64*2fcb3686SMichael Holzheu } 65*2fcb3686SMichael Holzheu rc = df->data_create(&data->buf, &data->buf_free_ptr, 66*2fcb3686SMichael Holzheu &data->size); 67*2fcb3686SMichael Holzheu if (rc) { 68*2fcb3686SMichael Holzheu mutex_unlock(&df->lock); 69*2fcb3686SMichael Holzheu kfree(data); 70*2fcb3686SMichael Holzheu return rc; 71*2fcb3686SMichael Holzheu } 72*2fcb3686SMichael Holzheu df->data = data; 73*2fcb3686SMichael Holzheu schedule_delayed_work(&df->data_free_work, HZ); 74*2fcb3686SMichael Holzheu } 75*2fcb3686SMichael Holzheu data = df->data; 76*2fcb3686SMichael Holzheu kref_get(&data->kref); 77*2fcb3686SMichael Holzheu mutex_unlock(&df->lock); 78*2fcb3686SMichael Holzheu 79*2fcb3686SMichael Holzheu rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); 80*2fcb3686SMichael Holzheu kref_put(&data->kref, hypfs_dbfs_data_free); 81*2fcb3686SMichael Holzheu return rc; 82*2fcb3686SMichael Holzheu } 83*2fcb3686SMichael Holzheu 84*2fcb3686SMichael Holzheu static const struct file_operations dbfs_ops = { 85*2fcb3686SMichael Holzheu .read = dbfs_read, 86*2fcb3686SMichael Holzheu .llseek = no_llseek, 87*2fcb3686SMichael Holzheu }; 88*2fcb3686SMichael Holzheu 89*2fcb3686SMichael Holzheu int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) 90*2fcb3686SMichael Holzheu { 91*2fcb3686SMichael Holzheu df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, 92*2fcb3686SMichael Holzheu &dbfs_ops); 93*2fcb3686SMichael Holzheu if (IS_ERR(df->dentry)) 94*2fcb3686SMichael Holzheu return PTR_ERR(df->dentry); 95*2fcb3686SMichael Holzheu mutex_init(&df->lock); 96*2fcb3686SMichael Holzheu INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed); 97*2fcb3686SMichael Holzheu return 0; 98*2fcb3686SMichael Holzheu } 99*2fcb3686SMichael Holzheu 100*2fcb3686SMichael Holzheu void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) 101*2fcb3686SMichael Holzheu { 102*2fcb3686SMichael Holzheu debugfs_remove(df->dentry); 103*2fcb3686SMichael Holzheu } 104*2fcb3686SMichael Holzheu 105*2fcb3686SMichael Holzheu int hypfs_dbfs_init(void) 106*2fcb3686SMichael Holzheu { 107*2fcb3686SMichael Holzheu dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); 108*2fcb3686SMichael Holzheu if (IS_ERR(dbfs_dir)) 109*2fcb3686SMichael Holzheu return PTR_ERR(dbfs_dir); 110*2fcb3686SMichael Holzheu return 0; 111*2fcb3686SMichael Holzheu } 112*2fcb3686SMichael Holzheu 113*2fcb3686SMichael Holzheu void hypfs_dbfs_exit(void) 114*2fcb3686SMichael Holzheu { 115*2fcb3686SMichael Holzheu debugfs_remove(dbfs_dir); 116*2fcb3686SMichael Holzheu } 117