2 * Copyright (C) 2005-2017 Junjiro R. Okajima
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.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <linux/debugfs.h>
26 #error DEBUG_FS depends upon SYSFS
29 static struct dentry
*dbgaufs
;
30 static const mode_t dbgaufs_mode
= S_IRUSR
| S_IRGRP
| S_IROTH
;
32 /* 20 is max digits length of ulong 64 */
39 * common function for all XINO files
41 static int dbgaufs_xi_release(struct inode
*inode __maybe_unused
,
44 kfree(file
->private_data
);
48 static int dbgaufs_xi_open(struct file
*xf
, struct file
*file
, int do_fcnt
)
52 struct dbgaufs_arg
*p
;
55 p
= kmalloc(sizeof(*p
), GFP_NOFS
);
61 file
->private_data
= p
;
65 err
= vfsub_getattr(&xf
->f_path
, &st
);
69 (p
->a
, sizeof(p
->a
), "%ld, %llux%u %lld\n",
70 (long)file_count(xf
), st
.blocks
, st
.blksize
,
73 p
->n
= snprintf(p
->a
, sizeof(p
->a
), "%llux%u %lld\n",
74 st
.blocks
, st
.blksize
,
76 AuDebugOn(p
->n
>= sizeof(p
->a
));
78 p
->n
= snprintf(p
->a
, sizeof(p
->a
), "err %d\n", err
);
87 static ssize_t
dbgaufs_xi_read(struct file
*file
, char __user
*buf
,
88 size_t count
, loff_t
*ppos
)
90 struct dbgaufs_arg
*p
;
92 p
= file
->private_data
;
93 return simple_read_from_buffer(buf
, count
, ppos
, p
->a
, p
->n
);
96 /* ---------------------------------------------------------------------- */
98 struct dbgaufs_plink_arg
{
103 static int dbgaufs_plink_release(struct inode
*inode __maybe_unused
,
106 free_page((unsigned long)file
->private_data
);
110 static int dbgaufs_plink_open(struct inode
*inode
, struct file
*file
)
113 unsigned long n
, sum
;
114 struct dbgaufs_plink_arg
*p
;
115 struct au_sbinfo
*sbinfo
;
116 struct super_block
*sb
;
117 struct au_sphlhead
*sphl
;
120 p
= (void *)get_zeroed_page(GFP_NOFS
);
125 sbinfo
= inode
->i_private
;
127 si_noflush_read_lock(sb
);
128 if (au_opt_test(au_mntflags(sb
), PLINK
)) {
129 limit
= PAGE_SIZE
- sizeof(p
->n
);
131 /* the number of buckets */
132 n
= snprintf(p
->a
+ p
->n
, limit
, "%d\n", AuPlink_NHASH
);
137 for (i
= 0, sphl
= sbinfo
->si_plink
;
140 n
= au_sphl_count(sphl
);
143 n
= snprintf(p
->a
+ p
->n
, limit
, "%lu ", n
);
146 if (unlikely(limit
<= 0))
149 p
->a
[p
->n
- 1] = '\n';
151 /* the sum of plinks */
152 n
= snprintf(p
->a
+ p
->n
, limit
, "%lu\n", sum
);
155 if (unlikely(limit
<= 0))
158 #define str "1\n0\n0\n"
159 p
->n
= sizeof(str
) - 1;
166 file
->private_data
= p
;
167 goto out
; /* success */
170 free_page((unsigned long)p
);
175 static ssize_t
dbgaufs_plink_read(struct file
*file
, char __user
*buf
,
176 size_t count
, loff_t
*ppos
)
178 struct dbgaufs_plink_arg
*p
;
180 p
= file
->private_data
;
181 return simple_read_from_buffer(buf
, count
, ppos
, p
->a
, p
->n
);
184 static const struct file_operations dbgaufs_plink_fop
= {
185 .owner
= THIS_MODULE
,
186 .open
= dbgaufs_plink_open
,
187 .release
= dbgaufs_plink_release
,
188 .read
= dbgaufs_plink_read
191 /* ---------------------------------------------------------------------- */
193 static int dbgaufs_xib_open(struct inode
*inode
, struct file
*file
)
196 struct au_sbinfo
*sbinfo
;
197 struct super_block
*sb
;
199 sbinfo
= inode
->i_private
;
201 si_noflush_read_lock(sb
);
202 err
= dbgaufs_xi_open(sbinfo
->si_xib
, file
, /*do_fcnt*/0);
207 static const struct file_operations dbgaufs_xib_fop
= {
208 .owner
= THIS_MODULE
,
209 .open
= dbgaufs_xib_open
,
210 .release
= dbgaufs_xi_release
,
211 .read
= dbgaufs_xi_read
214 /* ---------------------------------------------------------------------- */
216 #define DbgaufsXi_PREFIX "xi"
218 static int dbgaufs_xino_open(struct inode
*inode
, struct file
*file
)
222 struct au_sbinfo
*sbinfo
;
223 struct super_block
*sb
;
229 name
= &file
->f_path
.dentry
->d_name
;
230 if (unlikely(name
->len
< sizeof(DbgaufsXi_PREFIX
)
231 || memcmp(name
->name
, DbgaufsXi_PREFIX
,
232 sizeof(DbgaufsXi_PREFIX
) - 1)))
234 err
= kstrtol(name
->name
+ sizeof(DbgaufsXi_PREFIX
) - 1, 10, &l
);
238 sbinfo
= inode
->i_private
;
240 si_noflush_read_lock(sb
);
241 if (l
<= au_sbbot(sb
)) {
242 xf
= au_sbr(sb
, (aufs_bindex_t
)l
)->br_xino
.xi_file
;
243 err
= dbgaufs_xi_open(xf
, file
, /*do_fcnt*/1);
252 static const struct file_operations dbgaufs_xino_fop
= {
253 .owner
= THIS_MODULE
,
254 .open
= dbgaufs_xino_open
,
255 .release
= dbgaufs_xi_release
,
256 .read
= dbgaufs_xi_read
259 void dbgaufs_brs_del(struct super_block
*sb
, aufs_bindex_t bindex
)
262 struct au_branch
*br
;
263 struct au_xino_file
*xi
;
265 if (!au_sbi(sb
)->si_dbgaufs
)
269 for (; bindex
<= bbot
; bindex
++) {
270 br
= au_sbr(sb
, bindex
);
272 /* debugfs acquires the parent i_mutex */
274 debugfs_remove(xi
->xi_dbgaufs
);
276 xi
->xi_dbgaufs
= NULL
;
280 void dbgaufs_brs_add(struct super_block
*sb
, aufs_bindex_t bindex
)
282 struct au_sbinfo
*sbinfo
;
283 struct dentry
*parent
;
284 struct au_branch
*br
;
285 struct au_xino_file
*xi
;
287 char name
[sizeof(DbgaufsXi_PREFIX
) + 5]; /* "xi" bindex NULL */
290 parent
= sbinfo
->si_dbgaufs
;
295 for (; bindex
<= bbot
; bindex
++) {
296 snprintf(name
, sizeof(name
), DbgaufsXi_PREFIX
"%d", bindex
);
297 br
= au_sbr(sb
, bindex
);
299 AuDebugOn(xi
->xi_dbgaufs
);
300 /* debugfs acquires the parent i_mutex */
302 xi
->xi_dbgaufs
= debugfs_create_file(name
, dbgaufs_mode
, parent
,
303 sbinfo
, &dbgaufs_xino_fop
);
305 /* ignore an error */
306 if (unlikely(!xi
->xi_dbgaufs
))
307 AuWarn1("failed %s under debugfs\n", name
);
311 /* ---------------------------------------------------------------------- */
313 #ifdef CONFIG_AUFS_EXPORT
314 static int dbgaufs_xigen_open(struct inode
*inode
, struct file
*file
)
317 struct au_sbinfo
*sbinfo
;
318 struct super_block
*sb
;
320 sbinfo
= inode
->i_private
;
322 si_noflush_read_lock(sb
);
323 err
= dbgaufs_xi_open(sbinfo
->si_xigen
, file
, /*do_fcnt*/0);
328 static const struct file_operations dbgaufs_xigen_fop
= {
329 .owner
= THIS_MODULE
,
330 .open
= dbgaufs_xigen_open
,
331 .release
= dbgaufs_xi_release
,
332 .read
= dbgaufs_xi_read
335 static int dbgaufs_xigen_init(struct au_sbinfo
*sbinfo
)
340 * This function is a dynamic '__init' function actually,
341 * so the tiny check for si_rwsem is unnecessary.
343 /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
346 sbinfo
->si_dbgaufs_xigen
= debugfs_create_file
347 ("xigen", dbgaufs_mode
, sbinfo
->si_dbgaufs
, sbinfo
,
349 if (sbinfo
->si_dbgaufs_xigen
)
355 static int dbgaufs_xigen_init(struct au_sbinfo
*sbinfo
)
359 #endif /* CONFIG_AUFS_EXPORT */
361 /* ---------------------------------------------------------------------- */
363 void dbgaufs_si_fin(struct au_sbinfo
*sbinfo
)
366 * This function is a dynamic '__fin' function actually,
367 * so the tiny check for si_rwsem is unnecessary.
369 /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
371 debugfs_remove_recursive(sbinfo
->si_dbgaufs
);
372 sbinfo
->si_dbgaufs
= NULL
;
373 kobject_put(&sbinfo
->si_kobj
);
376 int dbgaufs_si_init(struct au_sbinfo
*sbinfo
)
379 char name
[SysaufsSiNameLen
];
382 * This function is a dynamic '__init' function actually,
383 * so the tiny check for si_rwsem is unnecessary.
385 /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
389 AuErr1("/debug/aufs is uninitialized\n");
394 sysaufs_name(sbinfo
, name
);
395 sbinfo
->si_dbgaufs
= debugfs_create_dir(name
, dbgaufs
);
396 if (unlikely(!sbinfo
->si_dbgaufs
))
398 kobject_get(&sbinfo
->si_kobj
);
400 sbinfo
->si_dbgaufs_xib
= debugfs_create_file
401 ("xib", dbgaufs_mode
, sbinfo
->si_dbgaufs
, sbinfo
,
403 if (unlikely(!sbinfo
->si_dbgaufs_xib
))
406 sbinfo
->si_dbgaufs_plink
= debugfs_create_file
407 ("plink", dbgaufs_mode
, sbinfo
->si_dbgaufs
, sbinfo
,
409 if (unlikely(!sbinfo
->si_dbgaufs_plink
))
412 err
= dbgaufs_xigen_init(sbinfo
);
414 goto out
; /* success */
417 dbgaufs_si_fin(sbinfo
);
422 /* ---------------------------------------------------------------------- */
424 void dbgaufs_fin(void)
426 debugfs_remove(dbgaufs
);
429 int __init
dbgaufs_init(void)
434 dbgaufs
= debugfs_create_dir(AUFS_NAME
, NULL
);