2009-03-24 18:24:24

by J. R. Okajima

[permalink] [raw]
Subject: [RFC Aufs2 #4 0/3] convert aufs entires from sysfs to debugfs

Follow the comments from Greg KH on LKML.
Move 'xib' and 'xi0 ... xiN' entries from sysaufs to debugfs.
They show how many disk blocks are consumed.

J. R. Okajima (3):
aufs: convert some aufs entries from sysfs to debugfs, new files
aufs: convert some aufs entries from sysfs to debugfs
aufs: convert some aufs entries from sysfs to debugfs, documentation

Documentation/ABI/testing/debugfs-aufs | 40 +++++
Documentation/ABI/testing/sysfs-aufs | 37 ----
Documentation/filesystems/aufs/README | 3 +-
Documentation/filesystems/aufs/aufs.5 | 57 ++++---
fs/aufs/Makefile | 1 +
fs/aufs/aufs.h | 1 +
fs/aufs/branch.c | 2 +-
fs/aufs/branch.h | 6 +-
fs/aufs/dbgaufs.c | 292 ++++++++++++++++++++++++++++++++
fs/aufs/dbgaufs.h | 68 ++++++++
fs/aufs/super.c | 5 +
fs/aufs/super.h | 19 ++
fs/aufs/sysaufs.c | 30 +++-
fs/aufs/sysaufs.h | 16 +-
fs/aufs/sysfs.c | 168 ++++---------------
15 files changed, 527 insertions(+), 218 deletions(-)
create mode 100644 Documentation/ABI/testing/debugfs-aufs
create mode 100644 fs/aufs/dbgaufs.c
create mode 100644 fs/aufs/dbgaufs.h


2009-03-24 18:24:40

by J. R. Okajima

[permalink] [raw]
Subject: [RFC Aufs2 #4 1/3] aufs: convert some aufs entries from sysfs to debugfs, new files

Follow the comments from Greg KH on LKML.
Move 'xib', 'xigen' and 'xi0 ... xiN' entries from sysaufs to debugfs.
They show how many disk blocks are consumed.
- new aufs entries under debugfs.
- new files dbgaufs.c and dbgaufs.h.
- it trusts that CONFIG_DEBUG_FS "depends on SYSFS".

Signed-off-by: J. R. Okajima <[email protected]>
---
fs/aufs/dbgaufs.c | 292 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/aufs/dbgaufs.h | 68 ++++++++++++
2 files changed, 360 insertions(+), 0 deletions(-)
create mode 100644 fs/aufs/dbgaufs.c
create mode 100644 fs/aufs/dbgaufs.h

diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
new file mode 100644
index 0000000..5cdeafa
--- /dev/null
+++ b/fs/aufs/dbgaufs.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * debugfs interface
+ */
+
+#include <linux/debugfs.h>
+#include "aufs.h"
+
+#ifndef CONFIG_SYSFS
+#error DEBUG_FS depends upon SYSFS
+#endif
+
+static struct dentry *dbgaufs;
+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
+
+/* 20 is max digits length of ulong 64 */
+struct dbgaufs_arg {
+ int n;
+ char a[20 * 4];
+};
+
+/*
+ * common function for all XINO files
+ */
+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
+ struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
+{
+ int err;
+ struct kstat st;
+ struct dbgaufs_arg *p;
+
+ err = -ENOMEM;
+ p = kmalloc(sizeof(*p), GFP_NOFS);
+ if (unlikely(!p))
+ goto out;
+
+ err = 0;
+ p->n = 0;
+ file->private_data = p;
+ if (!xf)
+ goto out;
+
+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
+ if (!err) {
+ if (do_fcnt)
+ p->n = snprintf
+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
+ (long)file_count(xf), st.blocks, st.blksize,
+ (long long)st.size);
+ else
+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
+ st.blocks, st.blksize,
+ (long long)st.size);
+ AuDebugOn(p->n >= sizeof(p->a));
+ } else {
+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
+ err = 0;
+ }
+
+ out:
+ return err;
+
+}
+
+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct dbgaufs_arg *p;
+
+ p = file->private_data;
+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
+{
+ struct au_sbinfo *sbinfo;
+
+ sbinfo = inode->i_private;
+ return dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
+}
+
+static struct file_operations dbgaufs_xib_fop = {
+ .open = dbgaufs_xib_open,
+ .release = dbgaufs_xi_release,
+ .read = dbgaufs_xi_read
+};
+
+/* ---------------------------------------------------------------------- */
+
+#define DbgaufsXi_PREFIX "xi"
+
+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
+{
+ int err;
+ long l;
+ struct au_sbinfo *sbinfo;
+ struct super_block *sb;
+ struct file *xf;
+ struct qstr *name;
+
+ err = -ENOENT;
+ xf = NULL;
+ name = &file->f_dentry->d_name;
+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
+ || memcmp(name->name, DbgaufsXi_PREFIX,
+ sizeof(DbgaufsXi_PREFIX) - 1)))
+ goto out;
+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
+ if (unlikely(err))
+ goto out;
+
+ sbinfo = inode->i_private;
+ sb = sbinfo->si_sb;
+ si_noflush_read_lock(sb);
+ if (l <= au_sbend(sb)) {
+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
+ } else
+ err = -ENOENT;
+ si_read_unlock(sb);
+
+ out:
+ return err;
+}
+
+static struct file_operations dbgaufs_xino_fop = {
+ .open = dbgaufs_xino_open,
+ .release = dbgaufs_xi_release,
+ .read = dbgaufs_xi_read
+};
+
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+ aufs_bindex_t bend;
+ struct au_branch *br;
+ struct au_xino_file *xi;
+
+ if (!au_sbi(sb)->si_dbgaufs)
+ return;
+
+ bend = au_sbend(sb);
+ for (; bindex <= bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ xi = &br->br_xino;
+ if (xi->xi_dbgaufs) {
+ debugfs_remove(xi->xi_dbgaufs);
+ xi->xi_dbgaufs = NULL;
+ }
+ }
+}
+
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+ struct au_sbinfo *sbinfo;
+ struct dentry *parent;
+ struct au_branch *br;
+ struct au_xino_file *xi;
+ aufs_bindex_t bend;
+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
+
+ sbinfo = au_sbi(sb);
+ parent = sbinfo->si_dbgaufs;
+ if (!parent)
+ return;
+
+ bend = au_sbend(sb);
+ for (; bindex <= bend; bindex++) {
+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
+ br = au_sbr(sb, bindex);
+ xi = &br->br_xino;
+ AuDebugOn(xi->xi_dbgaufs);
+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
+ sbinfo, &dbgaufs_xino_fop);
+ /* ignore an error */
+ if (unlikely(!xi->xi_dbgaufs))
+ AuWarn1("failed %s under debugfs\n", name);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_EXPORT
+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
+{
+ struct au_sbinfo *sbinfo;
+
+ sbinfo = inode->i_private;
+ return dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
+}
+
+static struct file_operations dbgaufs_xigen_fop = {
+ .open = dbgaufs_xigen_open,
+ .release = dbgaufs_xi_release,
+ .read = dbgaufs_xi_read
+};
+
+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
+{
+ int err;
+
+ err = -EIO;
+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
+ &dbgaufs_xigen_fop);
+ if (sbinfo->si_dbgaufs_xigen)
+ err = 0;
+
+ return err;
+}
+#else
+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
+{
+ return 0;
+}
+#endif /* CONFIG_AUFS_EXPORT */
+
+/* ---------------------------------------------------------------------- */
+
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
+{
+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
+ sbinfo->si_dbgaufs = NULL;
+ kobject_put(&sbinfo->si_kobj);
+}
+
+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
+{
+ int err;
+ char name[SysaufsSiNameLen];
+
+ err = -ENOENT;
+ if (!dbgaufs) {
+ AuErr1("/debug/aufs is uninitialized\n");
+ goto out;
+ }
+
+ err = -EIO;
+ sysaufs_name(sbinfo, name);
+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
+ if (unlikely(!sbinfo->si_dbgaufs))
+ goto out;
+ kobject_get(&sbinfo->si_kobj);
+
+ sbinfo->si_dbgaufs_xib = debugfs_create_file
+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
+ &dbgaufs_xib_fop);
+ if (unlikely(!sbinfo->si_dbgaufs_xib))
+ goto out_dir;
+
+ err = dbgaufs_xigen_init(sbinfo);
+ if (!err)
+ goto out; /* success */
+
+ out_dir:
+ dbgaufs_si_fin(sbinfo);
+ out:
+ return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void dbgaufs_fin(void)
+{
+ debugfs_remove(dbgaufs);
+}
+
+int __init dbgaufs_init(void)
+{
+ int err;
+
+ err = -EIO;
+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
+ if (dbgaufs)
+ err = 0;
+ return err;
+}
diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
new file mode 100644
index 0000000..7368292
--- /dev/null
+++ b/fs/aufs/dbgaufs.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * debugfs interface
+ */
+
+#ifndef __DBGAUFS_H__
+#define __DBGAUFS_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/aufs_type.h>
+
+struct au_sbinfo;
+#ifdef CONFIG_DEBUG_FS
+/* dbgaufs.c */
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
+void dbgaufs_fin(void);
+int __init dbgaufs_init(void);
+
+#else
+
+static inline
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+ /* empty */
+}
+
+static inline
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+ /* empty */
+}
+
+static inline
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
+{
+ /* empty */
+}
+
+static inline
+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
+{
+ return 0;
+}
+
+#define dbgaufs_fin() do {} while (0)
+
+static inline
+int __init dbgaufs_init(void);
+{
+ return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* __KERNEL__ */
+#endif /* __DBGAUFS_H__ */
--
1.6.1.284.g5dc13

2009-03-24 18:26:30

by J. R. Okajima

[permalink] [raw]
Subject: [RFC Aufs2 #4 3/3] aufs: convert some aufs entries from sysfs to debugfs, documentation

Follow the comments from Greg KH on LKML.
Move 'xib', 'xigen' and 'xi0 ... xiN' entries from sysaufs to debugfs.
They show how many disk blocks are consumed.
- move the description of some aufs entries from sysfs-aufs to debugfs-aufs.
- fix the manual.

Signed-off-by: J. R. Okajima <[email protected]>
---
Documentation/ABI/testing/debugfs-aufs | 40 ++++++++++++++++++++++
Documentation/ABI/testing/sysfs-aufs | 37 --------------------
Documentation/filesystems/aufs/README | 3 +-
Documentation/filesystems/aufs/aufs.5 | 57 ++++++++++++++++++-------------
4 files changed, 75 insertions(+), 62 deletions(-)
create mode 100644 Documentation/ABI/testing/debugfs-aufs

diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs
new file mode 100644
index 0000000..4110b94
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-aufs
@@ -0,0 +1,40 @@
+What: /debug/aufs/si_<id>/
+Date: March 2009
+Contact: J. R. Okajima <[email protected]>
+Description:
+ Under /debug/aufs, a directory named si_<id> is created
+ per aufs mount, where <id> is a unique id generated
+ internally.
+
+What: /debug/aufs/si_<id>/xib
+Date: March 2009
+Contact: J. R. Okajima <[email protected]>
+Description:
+ It shows the consumed blocks by xib (External Inode Number
+ Bitmap), its block size and file size.
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see
+ Documentation/filesystems/aufs/aufs.5 in detail.
+
+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
+Date: March 2009
+Contact: J. R. Okajima <[email protected]>
+Description:
+ It shows the consumed blocks by xino (External Inode Number
+ Translation Table), its link count, block size and file
+ size.
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see
+ Documentation/filesystems/aufs/aufs.5 in detail.
+
+What: /debug/aufs/si_<id>/xigen
+Date: March 2009
+Contact: J. R. Okajima <[email protected]>
+Description:
+ It shows the consumed blocks by xigen (External Inode
+ Generation Table), its block size and file size.
+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
+ be created.
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see
+ Documentation/filesystems/aufs/aufs.5 in detail.
diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs
index 1552d3e..ca49330 100644
--- a/Documentation/ABI/testing/sysfs-aufs
+++ b/Documentation/ABI/testing/sysfs-aufs
@@ -23,40 +23,3 @@ Description:
When the aufs mount option 'noxino' is specified, it
will be empty. About XINO files, see
Documentation/filesystems/aufs/aufs.5 in detail.
-
-What: /sys/fs/aufs/si_<id>/xib
-Date: March 2009
-Contact: J. R. Okajima <[email protected]>
-Description:
- It shows the consumed blocks by xib (External Inode Number
- Bitmap), its block size and file size.
- When the aufs mount option 'noxino' is specified, it
- will be empty. About XINO files, see
- Documentation/filesystems/aufs/aufs.5 in detail.
-
-What: /sys/fs/aufs/si_<id>/xino0, xino1 ... xinoN
-Date: March 2009
-Contact: J. R. Okajima <[email protected]>
-Description:
- It shows the consumed blocks by xino (External Inode Number
- Translation Table), its link count, block size and file
- size.
- When the aufs mount option 'noxino' is specified, it
- will be empty. About XINO files, see
- Documentation/filesystems/aufs/aufs.5 in detail.
-
-What: /sys/fs/aufs/si_<id>/xigen
-Date: March 2009
-Contact: J. R. Okajima <[email protected]>
-Description:
- It shows the consumed blocks by xigen (External Inode
- Generation Table), its block size and file size.
- If CONFIG_AUFS_EXPORT is disabled, this entry will not
- be created.
- When the aufs mount option 'noxino' is specified, it
- will be empty. About XINO files, see
- Documentation/filesystems/aufs/aufs.5 in detail.
-
-# Local variables: ;
-# mode: text;
-# End: ;
diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README
index 8d4ba1f..3e323ac 100644
--- a/Documentation/filesystems/aufs/README
+++ b/Documentation/filesystems/aufs/README
@@ -201,8 +201,9 @@ See sample dir in CVS tree on SourceForge.
When you have any problems or strange behaviour in aufs, please let me
know with:
- /proc/mounts (instead of the output of mount(8))
-- /sys/fs/aufs/* (if you have them)
- /sys/module/aufs/*
+- /sys/fs/aufs/* (if you have them)
+- /debug/aufs/* (if you have them)
- linux kernel version
if your kernel is not plain, for example modified by distributor,
the url where i can download its source is necessary too.
diff --git a/Documentation/filesystems/aufs/aufs.5 b/Documentation/filesystems/aufs/aufs.5
index b3bca05..b81baf1 100644
--- a/Documentation/filesystems/aufs/aufs.5
+++ b/Documentation/filesystems/aufs/aufs.5
@@ -1,4 +1,4 @@
-.ds AUFS_VERSION aufs2-base6
+.ds AUFS_VERSION aufs2
.ds AUFS_XINO_FNAME .aufs.xino
.ds AUFS_XINO_DEFPATH /tmp/.aufs.xino
.ds AUFS_DIRWH_DEF 3
@@ -156,6 +156,12 @@ unlinked. So you
cannot find this file, but it exists and is read/written frequently by
aufs.
(cf. External Inode Number Bitmap, Translation Table).
+
+If you enable CONFIG_SYSFS, the path of xino files are not shown in
+/proc/mounts (and /etc/mtab), instead it is shown in
+<sysfs>/fs/aufs/si_<id>/xi_path.
+Otherwise, it is shown in /proc/mounts unless it is not the default
+path.
.
.TP
.B noxino
@@ -325,24 +331,15 @@ Specifies to use the branch path data file under sysfs or not.
If the number of your branches is large or their path is long
and you meet the limitation of mount(8) ro /etc/mtab, you need to
enable CONFIG_SYSFS and set aufs module parameter brs=1.
-If your linux version is linux\-2.6.24 and earlier, you need to enable
-CONFIG_AUFS_SYSAUFS too.

When this parameter is set as 1, aufs does not show \[oq]br:\[cq] (or dirs=)
-mount option through /proc/mounts, and /sbin/mount.aufs does not put it
-to /etc/mtab. So you can keep yourself from the page limitation of
+mount option through /proc/mounts (and /etc/mtab). So you can
+keep yourself from the page limitation of
mount(8) or /etc/mtab.
Aufs shows branch paths through <sysfs>/fs/aufs/si_XXX/brNNN.
Actually the file under sysfs has also a size limitation, but I don\[aq]t
think it is harmful.

-The default is brs=0, which means <sysfs>/fs/aufs/si_XXX/brNNN does not exist
-and \[oq]br:\[cq] option will appear in /proc/mounts, and /etc/mtab if you
-install /sbin/mount.aufs.
-If you did not enable CONFIG_AUFS_SYSAUFS (for
-linux\-2.6.24 and earlier), this parameter will be
-ignored.
-
There is one more side effect in setting 1 to this parameter.
If you rename your branch, the branch path written in /etc/mtab will be
obsoleted and the future remount will meet some error due to the
@@ -352,13 +349,13 @@ If you set 1, /etc/mtab will not hold the branch path and you will not
meet such trouble. On the other hand, the entires for the
branch path under sysfs are generated dynamically. So it must not be obsoleted.
But I don\[aq]t think users want to rename branches so often.
+
+If CONFIG_SYSFS is disable, this paramater is always set to 0.
.
.TP
.B sysrq=key
Specifies MagicSysRq key for debugging aufs.
You need to enable both of CONFIG_MAGIC_SYSRQ and CONFIG_AUFS_DEBUG.
-If your linux version is linux\-2.6.24 and earlier, you need to enable
-CONFIG_AUFS_SYSAUFS too.
Currently this is for developers only.
The default is \[oq]a\[cq].
.
@@ -371,6 +368,10 @@ Currently this is for developers only.
The default is \[oq]0\[cq] (disable).

.\" ----------------------------------------------------------------------
+.SH Entries under Sysfs and Debugfs
+See linux/Documentation/ABI/*/{sys,debug}fs-aufs.
+
+.\" ----------------------------------------------------------------------
.SH Branch Syntax
.TP
.B dir_path[ =permission [ + attribute ] ]
@@ -384,7 +385,8 @@ permission flags for that branch.
Comma, colon and the permission flags string (including \[oq]=\[cq])in the path
are not allowed.

-Any filesystem can be a branch, except aufs, sysfs, procfs and unionfs.
+Any filesystem can be a branch, But some are not accepted such like
+sysfs, procfs and unionfs.
If you specify such filesystems as an aufs branch, aufs will return an error
saying it is unsupported.

@@ -559,6 +561,12 @@ will be \*[AUFS_XINO_DEFPATH].
.\" A user who executes mount(8) needs the privilege to create xino
.\" file.

+If you enable CONFIG_SYSFS, the path of xino files are not shown in
+/proc/mounts (and /etc/mtab), instead it is shown in
+<sysfs>/fs/aufs/si_<id>/xi_path.
+Otherwise, it is shown in /proc/mounts unless it is not the default
+path.
+
Those files are always opened and read/write by aufs frequently.
If your writable branch is on flash memory device, it is recommended
to put xino files on other than flash memory by specifying \[oq]xino=\[cq]
@@ -599,11 +607,11 @@ supported largest inode number is less than LLONG_MAX/8\-1.

The xino files are always hidden, i.e. removed. So you cannot
do \[oq]ls \-l xino_file\[cq].
-If you enable CONFIG_SYSFS, you can check these information through
-<sysfs>/fs/aufs/<si_id>/xino (for linux\-2.6.24 and earlier, you
-need to enable CONFIG_AUFS_SYSAUFS too).
-The first line in <sysfs>/fs/aufs/<si_id>/xino (and xigen) shows the
-information of the bitmap file, in the format of,
+If you enable CONFIG_DEBUG_FS, you can check these information through
+<debugfs>/aufs/<si_id>/{xib,xi[0-9]*,xigen}. xib is for the bitmap file,
+xi0 ix for the first branch, and xi1 is for the next. xigen is for the
+generation table.
+xib and xigen are in the format of,

.nf
<blocks>x<block size> <file size>
@@ -620,7 +628,7 @@ pre-allocation feature.
The rests are hidden xino file information in the format of,

.nf
-<branch index>: <file count>, <blocks>x<block size> <file size>
+<file count>, <blocks>x<block size> <file size>
.fi

If the file count is larger than 1, it means some of your branches are
@@ -630,7 +638,8 @@ since xino file is a sparse file, i.e. a hole in a file which does not
consume any disk blocks.

Once you unmount aufs, the xino files for that aufs are totally gone.
-It means that the inode number is not permanent.
+It means that the inode number is not permanent across umount or
+shutdown.

The xino files should be created on the filesystem except NFS.
If your first writable branch is NFS, you will need to specify xino
@@ -941,8 +950,8 @@ about the file will be discarded and aufs re-lookup it. So the data will
be updated.
When an error condition occurs between UDBA and aufs operation, aufs
will return an error, including EIO.
-To use this option, you need linux\-2.6.18 and later, and need to
-enable CONFIG_INOTIFY and CONFIG_AUFS_UDBA_INOTIFY.
+To use this option, you need to enable CONFIG_INOTIFY and
+CONFIG_AUFS_UDBA_INOTIFY.

To rename/rmdir a directory on a branch directory may reveal the same named
directory on the lower branch. Aufs tries re-lookuping the renamed
--
1.6.1.284.g5dc13

2009-03-24 18:26:48

by J. R. Okajima

[permalink] [raw]
Subject: [RFC Aufs2 #4 2/3] aufs: convert some aufs entries from sysfs to debugfs

Follow the comments from Greg KH on LKML.
Move 'xib', 'xigen' and 'xi0 ... xiN' entries from sysaufs to debugfs.
They show how many disk blocks are consumed.
- compile dbgaufs.c.
- remove 'xigen', 'xib' and 'xi0 ... xiN' entries from sysfs.
- new members of struct au_sbinfo for dentries under debugfs.
- replace members in struct au_xino_file by a dentry of debugfs.
- intialization and finalization for aufs entries under debugfs.
- show the xino file path in /proc/mounts only when CONFIG_SYSFS is disabled.
- minor enhancement, make sure that sysaufs_si_mask is not zero.

Signed-off-by: J. R. Okajima <[email protected]>
---
fs/aufs/Makefile | 1 +
fs/aufs/aufs.h | 1 +
fs/aufs/branch.c | 2 +-
fs/aufs/branch.h | 6 +-
fs/aufs/super.c | 5 ++
fs/aufs/super.h | 19 ++++++
fs/aufs/sysaufs.c | 30 +++++++---
fs/aufs/sysaufs.h | 16 +++--
fs/aufs/sysfs.c | 168 ++++++++++-------------------------------------------
9 files changed, 92 insertions(+), 156 deletions(-)

diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile
index 7f9e9a3..52d8498 100644
--- a/fs/aufs/Makefile
+++ b/fs/aufs/Makefile
@@ -13,6 +13,7 @@ aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \

# all are boolean
aufs-$(CONFIG_SYSFS) += sysfs.o
+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
aufs-$(CONFIG_AUFS_DEBUG) += debug.o
diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h
index a599aee..132e84e 100644
--- a/fs/aufs/aufs.h
+++ b/fs/aufs/aufs.h
@@ -23,6 +23,7 @@
#include "branch.h"
#include "cpup.h"
#include "dcsub.h"
+#include "dbgaufs.h"
#include "dentry.h"
#include "dir.h"
#include "file.h"
diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
index 232f5b3..5e11a11 100644
--- a/fs/aufs/branch.c
+++ b/fs/aufs/branch.c
@@ -304,7 +304,7 @@ static int au_br_init(struct au_branch *br, struct super_block *sb,
int err;

err = 0;
- br->br_xino.xi_file = NULL;
+ memset(&br->br_xino, 0, sizeof(br->br_xino));
mutex_init(&br->br_xino.xi_nondir_mtx);
br->br_perm = add->perm;
br->br_mnt = add->path.mnt; /* set first, mntget() later */
diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
index 838648f..ffe0c08 100644
--- a/fs/aufs/branch.h
+++ b/fs/aufs/branch.h
@@ -32,10 +32,8 @@ struct au_xino_file {

/* todo: make xino files an array to support huge inode number */

-#ifdef CONFIG_SYSFS
- /* an entry under sysfs per mount-point */
- char xi_name[8];
- struct attribute xi_attr;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *xi_dbgaufs;
#endif
};

diff --git a/fs/aufs/super.c b/fs/aufs/super.c
index 700f8c8..c8f4c97 100644
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
@@ -130,6 +130,9 @@ static void au_show_wbr_create(struct seq_file *m, int v,

static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
{
+#ifdef CONFIG_SYSFS
+ return 0;
+#else
int err;
const int len = sizeof(AUFS_XINO_FNAME) - 1;
aufs_bindex_t bindex, brid;
@@ -164,6 +167,7 @@ static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)

out:
return err;
+#endif
}

/* seq_file will re-call me in case of too long string */
@@ -394,6 +398,7 @@ static void aufs_put_super(struct super_block *sb)
return;

aufs_umount_begin(sb);
+ dbgaufs_si_fin(sbinfo);
kobject_put(&sbinfo->si_kobj);
}

diff --git a/fs/aufs/super.h b/fs/aufs/super.h
index 83721ef..95420ca 100644
--- a/fs/aufs/super.h
+++ b/fs/aufs/super.h
@@ -135,6 +135,12 @@ struct au_sbinfo {
* but using sysfs is majority.
*/
struct kobject si_kobj;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
+#ifdef CONFIG_AUFS_EXPORT
+ struct dentry *si_dbgaufs_xigen;
+#endif
+#endif

/* dirty, necessary for unmounting, sysfs and sysrq */
struct super_block *si_sb;
@@ -193,6 +199,19 @@ static inline struct au_sbinfo *au_sbi(struct super_block *sb)

/* ---------------------------------------------------------------------- */

+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
+{
+#ifdef CONFIG_DEBUG_FS
+ sbinfo->si_dbgaufs = NULL;
+ sbinfo->si_dbgaufs_xib = NULL;
+#ifdef CONFIG_AUFS_EXPORT
+ sbinfo->si_dbgaufs_xigen = NULL;
+#endif
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+
/* lock superblock. mainly for entry point functions */
/*
* si_noflush_read_lock, si_noflush_write_lock,
diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
index c6fde2c..623f2e6 100644
--- a/fs/aufs/sysaufs.c
+++ b/fs/aufs/sysaufs.c
@@ -25,11 +25,9 @@ struct kset *sysaufs_ket;
.show = sysaufs_si_##_name, \
}

-static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path),
- sysaufs_si_attr_xib = AuSiAttr(xib);
+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
struct attribute *sysaufs_si_attrs[] = {
&sysaufs_si_attr_xi_path.attr,
- &sysaufs_si_attr_xib.attr,
NULL,
};

@@ -50,14 +48,23 @@ int sysaufs_si_init(struct au_sbinfo *sbinfo)
int err;

sbinfo->si_kobj.kset = sysaufs_ket;
- err = kobject_init_and_add(&sbinfo->si_kobj, &au_sbi_ktype,
- /*&sysaufs_ket->kobj*/NULL,
- "si_%lx", sysaufs_si_id(sbinfo));
+ /* cf. sysaufs_name() */
+ err = kobject_init_and_add
+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
+
+ dbgaufs_si_null(sbinfo);
+ if (!err) {
+ err = dbgaufs_si_init(sbinfo);
+ if (unlikely(err))
+ kobject_put(&sbinfo->si_kobj);
+ }
return err;
}

void sysaufs_fin(void)
{
+ dbgaufs_fin();
sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
kset_unregister(sysaufs_ket);
}
@@ -66,16 +73,23 @@ int __init sysaufs_init(void)
{
int err;

- get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
+ do {
+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
+ } while (!sysaufs_si_mask);

sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
err = PTR_ERR(sysaufs_ket);
if (IS_ERR(sysaufs_ket))
goto out;
err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
- if (unlikely(err))
+ if (unlikely(err)) {
kset_unregister(sysaufs_ket);
+ goto out;
+ }

+ err = dbgaufs_init();
+ if (unlikely(err))
+ sysaufs_fin();
out:
return err;
}
diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
index 71a0bba..c1202fa 100644
--- a/fs/aufs/sysaufs.h
+++ b/fs/aufs/sysaufs.h
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/sysfs.h>
#include <linux/aufs_type.h>
+#include "module.h"

struct sysaufs_si_attr {
struct attribute attr;
@@ -43,13 +44,20 @@ static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
return sysaufs_si_mask ^ (unsigned long)sbinfo;
}

+#define SysaufsSiNamePrefix "si_"
+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
+{
+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
+ sysaufs_si_id(sbinfo));
+}
+
struct au_branch;
#ifdef CONFIG_SYSFS
/* sysfs.c */
extern struct attribute_group *sysaufs_attr_group;

int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
-int sysaufs_si_xib(struct seq_file *seq, struct super_block *sb);
ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
char *buf);

@@ -69,12 +77,6 @@ int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
}

static inline
-int sysaufs_si_xib(struct seq_file *seq, struct super_block *sb)
-{
- return 0;
-}
-
-static inline
ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
index 9bcdce2..496a2fc 100644
--- a/fs/aufs/sysfs.c
+++ b/fs/aufs/sysfs.c
@@ -40,60 +40,6 @@ int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
return err;
}

-static int sysaufs_xi_attr(struct seq_file *seq, struct file *xf,
- struct kstat *st)
-{
- int err;
-
- err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, st);
- if (!err)
- seq_printf(seq, "%llux%lu %lld\n",
- st->blocks, st->blksize, (long long)st->size);
- else
- seq_printf(seq, "err %d\n", err);
-
- return err;
-}
-
-int sysaufs_si_xib(struct seq_file *seq, struct super_block *sb)
-{
- int err;
- struct kstat st;
-
- err = 0;
- if (au_opt_test(au_mntflags(sb), XINO))
- err = sysaufs_xi_attr(seq, au_sbi(sb)->si_xib, &st);
- return err;
-}
-
-static int sysaufs_si_xino(struct seq_file *seq, struct super_block *sb,
- aufs_bindex_t bindex)
-{
- int err;
- struct kstat st;
- struct file *xf;
-
- err = 0;
- if (!au_opt_test(au_mntflags(sb), XINO))
- goto out; /* success */
-
- AuDbg("b%d\n", bindex);
-
- xf = au_sbr(sb, bindex)->br_xino.xi_file;
- if (xf) {
- err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
- if (!err)
- seq_printf(seq, "%ld, %llux%lu %lld\n",
- (long)file_count(xf), st.blocks, st.blksize,
- (long long)st.size);
- else
- seq_printf(seq, "err %d\n", err);
- }
-
- out:
- return err;
-}
-
/*
* the lifetime of branch is independent from the entry under sysfs.
* sysfs handles the lifetime of the entry, and never call ->show() after it is
@@ -138,7 +84,6 @@ static struct seq_file *au_seq(char *p, ssize_t len)
}

#define SysaufsBr_PREFIX "br"
-#define SysaufsXi_PREFIX "xi"

/* todo: file size may exceed PAGE_SIZE */
ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
@@ -152,26 +97,6 @@ ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
struct seq_file *seq;
char *name;
struct attribute **cattr;
- static struct {
- const int prefix_len;
- char *prefix;
- int (*func)(struct seq_file *seq, struct super_block *sb,
- aufs_bindex_t bindex);
- } a[] = {
- {
- .prefix_len = sizeof(SysaufsBr_PREFIX) - 1,
- .prefix = SysaufsBr_PREFIX,
- .func = sysaufs_si_br
- },
- {
- .prefix_len = sizeof(SysaufsXi_PREFIX) - 1,
- .prefix = SysaufsXi_PREFIX,
- .func = sysaufs_si_xino
- },
- {
- .prefix_len = 0
- }
- }, *p;

sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
sb = sbinfo->si_sb;
@@ -193,22 +118,17 @@ ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
cattr++;
}

- p = a;
bend = au_sbend(sb);
- while (p->prefix_len) {
- if (!strncmp(name, p->prefix, p->prefix_len)) {
- name += p->prefix_len;
- err = strict_strtol(name, 10, &l);
- if (!err) {
- if (l <= bend)
- err = p->func(seq, sb,
- (aufs_bindex_t)l);
- else
- err = -ENOENT;
- }
- goto out_seq;
+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
+ name += sizeof(SysaufsBr_PREFIX) - 1;
+ err = strict_strtol(name, 10, &l);
+ if (!err) {
+ if (l <= bend)
+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
+ else
+ err = -ENOENT;
}
- p++;
+ goto out_seq;
}
BUG();

@@ -229,74 +149,50 @@ ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,

void sysaufs_br_init(struct au_branch *br)
{
- struct au_xino_file *xi;
-
br->br_attr.name = br->br_name;
br->br_attr.mode = S_IRUGO;
br->br_attr.owner = THIS_MODULE;
-
- xi = &br->br_xino;
- xi->xi_attr.name = xi->xi_name;
- xi->xi_attr.mode = S_IRUGO;
- xi->xi_attr.owner = THIS_MODULE;
}

void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
{
struct au_branch *br;
- struct au_xino_file *xi;
struct kobject *kobj;
- aufs_bindex_t bend, bi;
+ aufs_bindex_t bend;
+
+ dbgaufs_brs_del(sb, bindex);
+
+ if (!sysaufs_brs)
+ return;

kobj = &au_sbi(sb)->si_kobj;
bend = au_sbend(sb);
- for (bi = bindex; bi <= bend; bi++) {
- br = au_sbr(sb, bi);
- xi = &br->br_xino;
- sysfs_remove_file(kobj, &xi->xi_attr);
+ for (; bindex <= bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ sysfs_remove_file(kobj, &br->br_attr);
}
-
- if (sysaufs_brs)
- for (; bindex <= bend; bindex++) {
- br = au_sbr(sb, bindex);
- sysfs_remove_file(kobj, &br->br_attr);
- }
-}
-
-static void sysaufs_brs_do_add(struct kobject *kobj, struct attribute *attr,
- char name[], int nlen, char prefix[],
- aufs_bindex_t bindex)
-{
- int err;
-
- snprintf(name, nlen, "%s%d", prefix, bindex);
- err = sysfs_create_file(kobj, attr);
- if (unlikely(err))
- AuWarn("failed %s under sysfs(%d)\n", name, err);
}

void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
{
- aufs_bindex_t bend, bi;
+ int err;
+ aufs_bindex_t bend;
struct kobject *kobj;
struct au_branch *br;
- struct au_xino_file *xi;
+
+ dbgaufs_brs_add(sb, bindex);
+
+ if (!sysaufs_brs)
+ return;

kobj = &au_sbi(sb)->si_kobj;
bend = au_sbend(sb);
- for (bi = bindex; bi <= bend; bi++) {
- br = au_sbr(sb, bi);
- xi = &br->br_xino;
- /* todo: create link for shared xino */
- sysaufs_brs_do_add(kobj, &xi->xi_attr, xi->xi_name,
- sizeof(xi->xi_name), SysaufsXi_PREFIX, bi);
+ for (; bindex <= bend; bindex++) {
+ br = au_sbr(sb, bindex);
+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
+ "%d", bindex);
+ err = sysfs_create_file(kobj, &br->br_attr);
+ if (unlikely(err))
+ AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
}
-
- if (sysaufs_brs)
- for (; bindex <= bend; bindex++) {
- br = au_sbr(sb, bindex);
- sysaufs_brs_do_add(kobj, &br->br_attr, br->br_name,
- sizeof(br->br_name),
- SysaufsBr_PREFIX, bindex);
- }
}
--
1.6.1.284.g5dc13