cpufreq: OMAP: always use max clock for regulator
[pandora-kernel.git] / fs / aufs / dbgaufs.c
1 /*
2  * Copyright (C) 2005-2012 Junjiro R. Okajima
3  *
4  * This program, aufs is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * debugfs interface
21  */
22
23 #include <linux/debugfs.h>
24 #include "aufs.h"
25
26 #ifndef CONFIG_SYSFS
27 #error DEBUG_FS depends upon SYSFS
28 #endif
29
30 static struct dentry *dbgaufs;
31 static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
32
33 /* 20 is max digits length of ulong 64 */
34 struct dbgaufs_arg {
35         int n;
36         char a[20 * 4];
37 };
38
39 /*
40  * common function for all XINO files
41  */
42 static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
43                               struct file *file)
44 {
45         kfree(file->private_data);
46         return 0;
47 }
48
49 static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
50 {
51         int err;
52         struct kstat st;
53         struct dbgaufs_arg *p;
54
55         err = -ENOMEM;
56         p = kmalloc(sizeof(*p), GFP_NOFS);
57         if (unlikely(!p))
58                 goto out;
59
60         err = 0;
61         p->n = 0;
62         file->private_data = p;
63         if (!xf)
64                 goto out;
65
66         err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
67         if (!err) {
68                 if (do_fcnt)
69                         p->n = snprintf
70                                 (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
71                                  (long)file_count(xf), st.blocks, st.blksize,
72                                  (long long)st.size);
73                 else
74                         p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
75                                         st.blocks, st.blksize,
76                                         (long long)st.size);
77                 AuDebugOn(p->n >= sizeof(p->a));
78         } else {
79                 p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
80                 err = 0;
81         }
82
83 out:
84         return err;
85
86 }
87
88 static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
89                                size_t count, loff_t *ppos)
90 {
91         struct dbgaufs_arg *p;
92
93         p = file->private_data;
94         return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
95 }
96
97 /* ---------------------------------------------------------------------- */
98
99 static int dbgaufs_xib_open(struct inode *inode, struct file *file)
100 {
101         int err;
102         struct au_sbinfo *sbinfo;
103         struct super_block *sb;
104
105         sbinfo = inode->i_private;
106         sb = sbinfo->si_sb;
107         si_noflush_read_lock(sb);
108         err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
109         si_read_unlock(sb);
110         return err;
111 }
112
113 static const struct file_operations dbgaufs_xib_fop = {
114         .owner          = THIS_MODULE,
115         .open           = dbgaufs_xib_open,
116         .release        = dbgaufs_xi_release,
117         .read           = dbgaufs_xi_read
118 };
119
120 /* ---------------------------------------------------------------------- */
121
122 #define DbgaufsXi_PREFIX "xi"
123
124 static int dbgaufs_xino_open(struct inode *inode, struct file *file)
125 {
126         int err;
127         long l;
128         struct au_sbinfo *sbinfo;
129         struct super_block *sb;
130         struct file *xf;
131         struct qstr *name;
132
133         err = -ENOENT;
134         xf = NULL;
135         name = &file->f_dentry->d_name;
136         if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
137                      || memcmp(name->name, DbgaufsXi_PREFIX,
138                                sizeof(DbgaufsXi_PREFIX) - 1)))
139                 goto out;
140         err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
141         if (unlikely(err))
142                 goto out;
143
144         sbinfo = inode->i_private;
145         sb = sbinfo->si_sb;
146         si_noflush_read_lock(sb);
147         if (l <= au_sbend(sb)) {
148                 xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
149                 err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
150         } else
151                 err = -ENOENT;
152         si_read_unlock(sb);
153
154 out:
155         return err;
156 }
157
158 static const struct file_operations dbgaufs_xino_fop = {
159         .owner          = THIS_MODULE,
160         .open           = dbgaufs_xino_open,
161         .release        = dbgaufs_xi_release,
162         .read           = dbgaufs_xi_read
163 };
164
165 void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
166 {
167         aufs_bindex_t bend;
168         struct au_branch *br;
169         struct au_xino_file *xi;
170
171         if (!au_sbi(sb)->si_dbgaufs)
172                 return;
173
174         bend = au_sbend(sb);
175         for (; bindex <= bend; bindex++) {
176                 br = au_sbr(sb, bindex);
177                 xi = &br->br_xino;
178                 if (xi->xi_dbgaufs) {
179                         debugfs_remove(xi->xi_dbgaufs);
180                         xi->xi_dbgaufs = NULL;
181                 }
182         }
183 }
184
185 void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
186 {
187         struct au_sbinfo *sbinfo;
188         struct dentry *parent;
189         struct au_branch *br;
190         struct au_xino_file *xi;
191         aufs_bindex_t bend;
192         char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
193
194         sbinfo = au_sbi(sb);
195         parent = sbinfo->si_dbgaufs;
196         if (!parent)
197                 return;
198
199         bend = au_sbend(sb);
200         for (; bindex <= bend; bindex++) {
201                 snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
202                 br = au_sbr(sb, bindex);
203                 xi = &br->br_xino;
204                 AuDebugOn(xi->xi_dbgaufs);
205                 xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
206                                                      sbinfo, &dbgaufs_xino_fop);
207                 /* ignore an error */
208                 if (unlikely(!xi->xi_dbgaufs))
209                         AuWarn1("failed %s under debugfs\n", name);
210         }
211 }
212
213 /* ---------------------------------------------------------------------- */
214
215 #ifdef CONFIG_AUFS_EXPORT
216 static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
217 {
218         int err;
219         struct au_sbinfo *sbinfo;
220         struct super_block *sb;
221
222         sbinfo = inode->i_private;
223         sb = sbinfo->si_sb;
224         si_noflush_read_lock(sb);
225         err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
226         si_read_unlock(sb);
227         return err;
228 }
229
230 static const struct file_operations dbgaufs_xigen_fop = {
231         .owner          = THIS_MODULE,
232         .open           = dbgaufs_xigen_open,
233         .release        = dbgaufs_xi_release,
234         .read           = dbgaufs_xi_read
235 };
236
237 static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
238 {
239         int err;
240
241         /*
242          * This function is a dynamic '__init' fucntion actually,
243          * so the tiny check for si_rwsem is unnecessary.
244          */
245         /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
246
247         err = -EIO;
248         sbinfo->si_dbgaufs_xigen = debugfs_create_file
249                 ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
250                  &dbgaufs_xigen_fop);
251         if (sbinfo->si_dbgaufs_xigen)
252                 err = 0;
253
254         return err;
255 }
256 #else
257 static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
258 {
259         return 0;
260 }
261 #endif /* CONFIG_AUFS_EXPORT */
262
263 /* ---------------------------------------------------------------------- */
264
265 void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
266 {
267         /*
268          * This function is a dynamic '__init' fucntion actually,
269          * so the tiny check for si_rwsem is unnecessary.
270          */
271         /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
272
273         debugfs_remove_recursive(sbinfo->si_dbgaufs);
274         sbinfo->si_dbgaufs = NULL;
275         kobject_put(&sbinfo->si_kobj);
276 }
277
278 int dbgaufs_si_init(struct au_sbinfo *sbinfo)
279 {
280         int err;
281         char name[SysaufsSiNameLen];
282
283         /*
284          * This function is a dynamic '__init' fucntion actually,
285          * so the tiny check for si_rwsem is unnecessary.
286          */
287         /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
288
289         err = -ENOENT;
290         if (!dbgaufs) {
291                 AuErr1("/debug/aufs is uninitialized\n");
292                 goto out;
293         }
294
295         err = -EIO;
296         sysaufs_name(sbinfo, name);
297         sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
298         if (unlikely(!sbinfo->si_dbgaufs))
299                 goto out;
300         kobject_get(&sbinfo->si_kobj);
301
302         sbinfo->si_dbgaufs_xib = debugfs_create_file
303                 ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
304                  &dbgaufs_xib_fop);
305         if (unlikely(!sbinfo->si_dbgaufs_xib))
306                 goto out_dir;
307
308         err = dbgaufs_xigen_init(sbinfo);
309         if (!err)
310                 goto out; /* success */
311
312 out_dir:
313         dbgaufs_si_fin(sbinfo);
314 out:
315         return err;
316 }
317
318 /* ---------------------------------------------------------------------- */
319
320 void dbgaufs_fin(void)
321 {
322         debugfs_remove(dbgaufs);
323 }
324
325 int __init dbgaufs_init(void)
326 {
327         int err;
328
329         err = -EIO;
330         dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
331         if (dbgaufs)
332                 err = 0;
333         return err;
334 }