diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:50:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:50:50 -0500 |
commit | fb5131e1880ea1ba3ba7197cd5cc66c9c288f715 (patch) | |
tree | f0d9f25f9079727b9ead5a2b4cc85a0fea9b4668 /arch/s390/hypfs/hypfs_dbfs.c | |
parent | d074b104cefcb6e8ded55a53e62fed59a246f55d (diff) | |
parent | 8e1023016cf17152972b98bce6c144834a4916d5 (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (65 commits)
[S390] prevent unneccesary loops_per_jiffy recalculation
[S390] cpuinfo: use get_online_cpus() instead of preempt_disable()
[S390] smp: remove cpu hotplug messages
[S390] mutex: enable spinning mutex on s390
[S390] mutex: Introduce arch_mutex_cpu_relax()
[S390] cio: fix ccwgroup unregistration race condition
[S390] perf: add DWARF register lookup for s390
[S390] cleanup ftrace backend functions
[S390] ptrace cleanup
[S390] smp/idle: call init_idle() before starting a new cpu
[S390] smp: delay idle task creation
[S390] dasd: Correct retry counter for terminated I/O.
[S390] dasd: Add support for raw ECKD access.
[S390] dasd: Prevent deadlock during suspend/resume.
[S390] dasd: Improve handling of stolen DASD reservation
[S390] dasd: do path verification for paths added at runtime
[S390] dasd: add High Performance FICON multitrack support
[S390] cio: reduce memory consumption of itcw structures
[S390] nmi: enable machine checks early
[S390] qeth: buffer count imbalance
...
Diffstat (limited to 'arch/s390/hypfs/hypfs_dbfs.c')
-rw-r--r-- | arch/s390/hypfs/hypfs_dbfs.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c new file mode 100644 index 000000000000..b478013b7fec --- /dev/null +++ b/arch/s390/hypfs/hypfs_dbfs.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Hypervisor filesystem for Linux on s390 - debugfs interface | ||
3 | * | ||
4 | * Copyright (C) IBM Corp. 2010 | ||
5 | * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> | ||
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; | ||
73 | schedule_delayed_work(&df->data_free_work, HZ); | ||
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 | |||
89 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | ||
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 | |||
100 | void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) | ||
101 | { | ||
102 | debugfs_remove(df->dentry); | ||
103 | } | ||
104 | |||
105 | int hypfs_dbfs_init(void) | ||
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 | } | ||