Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hypfs_dbfs.c
Go to the documentation of this file.
1 /*
2  * Hypervisor filesystem for Linux on s390 - debugfs interface
3  *
4  * Copyright IBM Corp. 2010
5  * Author(s): Michael Holzheu <[email protected]>
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;
20  kref_init(&data->kref);
21  data->dbfs_file = f;
22  return data;
23 }
24 
25 static void hypfs_dbfs_data_free(struct kref *kref)
26 {
27  struct hypfs_dbfs_data *data;
28 
29  data = container_of(kref, struct hypfs_dbfs_data, kref);
30  data->dbfs_file->data_free(data->buf_free_ptr);
31  kfree(data);
32 }
33 
34 static void data_free_delayed(struct work_struct *work)
35 {
36  struct hypfs_dbfs_data *data;
37  struct hypfs_dbfs_file *df;
38 
39  df = container_of(work, struct hypfs_dbfs_file, data_free_work.work);
40  mutex_lock(&df->lock);
41  data = df->data;
42  df->data = NULL;
43  mutex_unlock(&df->lock);
44  kref_put(&data->kref, hypfs_dbfs_data_free);
45 }
46 
47 static ssize_t dbfs_read(struct file *file, char __user *buf,
48  size_t size, loff_t *ppos)
49 {
50  struct hypfs_dbfs_data *data;
51  struct hypfs_dbfs_file *df;
52  ssize_t rc;
53 
54  if (*ppos != 0)
55  return 0;
56 
57  df = file->f_path.dentry->d_inode->i_private;
58  mutex_lock(&df->lock);
59  if (!df->data) {
60  data = hypfs_dbfs_data_alloc(df);
61  if (!data) {
62  mutex_unlock(&df->lock);
63  return -ENOMEM;
64  }
65  rc = df->data_create(&data->buf, &data->buf_free_ptr,
66  &data->size);
67  if (rc) {
68  mutex_unlock(&df->lock);
69  kfree(data);
70  return rc;
71  }
72  df->data = data;
74  }
75  data = df->data;
76  kref_get(&data->kref);
77  mutex_unlock(&df->lock);
78 
79  rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size);
80  kref_put(&data->kref, hypfs_dbfs_data_free);
81  return rc;
82 }
83 
84 static const struct file_operations dbfs_ops = {
85  .read = dbfs_read,
86  .llseek = no_llseek,
87 };
88 
90 {
91  df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
92  &dbfs_ops);
93  if (IS_ERR(df->dentry))
94  return PTR_ERR(df->dentry);
95  mutex_init(&df->lock);
96  INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed);
97  return 0;
98 }
99 
101 {
102  debugfs_remove(df->dentry);
103 }
104 
106 {
107  dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
108  if (IS_ERR(dbfs_dir))
109  return PTR_ERR(dbfs_dir);
110  return 0;
111 }
112 
113 void hypfs_dbfs_exit(void)
114 {
115  debugfs_remove(dbfs_dir);
116 }