Commit 3cb74551 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: superblock op



Implement basic sb_op->show_options(), statfs() and sync_fs() simply.
- show_options() doesn't print the default values (AuOpt_Def).
- statfs() will have an option to summarize the numbers from branches
  (in later commit).
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 2b77ce86
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/iversion.h> #include <linux/iversion.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/statfs.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "aufs.h" #include "aufs.h"
...@@ -75,7 +76,6 @@ out: ...@@ -75,7 +76,6 @@ out:
} }
/* lock free root dinfo */ /* lock free root dinfo */
/* re-commit later */ __maybe_unused
static int au_show_brs(struct seq_file *seq, struct super_block *sb) static int au_show_brs(struct seq_file *seq, struct super_block *sb)
{ {
int err; int err;
...@@ -120,7 +120,6 @@ static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, ...@@ -120,7 +120,6 @@ static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
AuDebugOn(strlen(fmt) >= len); AuDebugOn(strlen(fmt) >= len);
} }
/* re-commit later */ __maybe_unused
static void au_show_wbr_create(struct seq_file *m, int v, static void au_show_wbr_create(struct seq_file *m, int v,
struct au_sbinfo *sbinfo) struct au_sbinfo *sbinfo)
{ {
...@@ -165,7 +164,6 @@ static void au_show_wbr_create(struct seq_file *m, int v, ...@@ -165,7 +164,6 @@ static void au_show_wbr_create(struct seq_file *m, int v,
} }
} }
/* re-commit later */ __maybe_unused
static int au_show_xino(struct seq_file *seq, struct super_block *sb) static int au_show_xino(struct seq_file *seq, struct super_block *sb)
{ {
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
...@@ -210,6 +208,138 @@ out: ...@@ -210,6 +208,138 @@ out:
#endif #endif
} }
/* seq_file will re-call me in case of too long string */
static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
{
int err;
unsigned int mnt_flags, v;
struct super_block *sb;
struct au_sbinfo *sbinfo;
#define AuBool(name, str) do { \
v = au_opt_test(mnt_flags, name); \
if (v != au_opt_test(AuOpt_Def, name)) \
seq_printf(m, ",%s" #str, v ? "" : "no"); \
} while (0)
#define AuStr(name, str) do { \
v = mnt_flags & AuOptMask_##name; \
if (v != (AuOpt_Def & AuOptMask_##name)) \
seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
} while (0)
#define AuUInt(name, str, val) do { \
if (val != AUFS_##name##_DEF) \
seq_printf(m, "," #str "=%u", val); \
} while (0)
sb = dentry->d_sb;
#if 0
if (sb->s_flags & SB_I_VERSION)
seq_puts(m, ",i_version");
#endif
/* lock free root dinfo */
si_noflush_read_lock(sb);
sbinfo = au_sbi(sb);
seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
mnt_flags = au_mntflags(sb);
if (au_opt_test(mnt_flags, XINO)) {
err = au_show_xino(m, sb);
if (unlikely(err))
goto out;
} else
seq_puts(m, ",noxino");
AuBool(TRUNC_XINO, trunc_xino);
AuStr(UDBA, udba);
AuBool(PLINK, plink);
AuBool(DIO, dio);
v = sbinfo->si_wbr_create;
if (v != AuWbrCreate_Def)
au_show_wbr_create(m, v, sbinfo);
v = sbinfo->si_wbr_copyup;
if (v != AuWbrCopyup_Def)
seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
AuUInt(RDCACHE, rdcache, v);
AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
out:
/* be sure to print "br:" last */
if (!sysaufs_brs) {
seq_puts(m, ",br:");
au_show_brs(m, sb);
}
si_read_unlock(sb);
return 0;
#undef AuBool
#undef AuStr
#undef AuUInt
}
/* ---------------------------------------------------------------------- */
static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
int err;
struct path h_path;
struct super_block *sb;
/* lock free root dinfo */
sb = dentry->d_sb;
si_noflush_read_lock(sb);
/* sb->s_root for NFS is unreliable */
h_path.mnt = au_sbr_mnt(sb, 0);
h_path.dentry = h_path.mnt->mnt_root;
err = vfs_statfs(&h_path, buf);
si_read_unlock(sb);
if (!err) {
buf->f_type = AUFS_SUPER_MAGIC;
buf->f_namelen = AUFS_MAX_NAMELEN;
memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
}
/* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
return err;
}
/* ---------------------------------------------------------------------- */
static int aufs_sync_fs(struct super_block *sb, int wait)
{
int err, e;
aufs_bindex_t bbot, bindex;
struct au_branch *br;
struct super_block *h_sb;
err = 0;
si_noflush_read_lock(sb);
bbot = au_sbbot(sb);
for (bindex = 0; bindex <= bbot; bindex++) {
br = au_sbr(sb, bindex);
if (!au_br_writable(br->br_perm))
continue;
h_sb = au_sbr_sb(sb, bindex);
e = vfsub_sync_filesystem(h_sb, wait);
if (unlikely(e && !err))
err = e;
/* go on even if an error happens */
}
si_read_unlock(sb);
return err;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* final actions when unmounting a file system */ /* final actions when unmounting a file system */
...@@ -565,7 +695,10 @@ static const struct super_operations aufs_sop = { ...@@ -565,7 +695,10 @@ static const struct super_operations aufs_sop = {
.destroy_inode = aufs_destroy_inode, .destroy_inode = aufs_destroy_inode,
/* always deleting, no clearing */ /* always deleting, no clearing */
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.show_options = aufs_show_options,
.statfs = aufs_statfs,
.put_super = aufs_put_super, .put_super = aufs_put_super,
.sync_fs = aufs_sync_fs,
.remount_fs = aufs_remount_fs .remount_fs = aufs_remount_fs
}; };
......
...@@ -12,6 +12,21 @@ ...@@ -12,6 +12,21 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include "aufs.h" #include "aufs.h"
int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
{
int err;
lockdep_off();
down_read(&h_sb->s_umount);
err = __sync_filesystem(h_sb, wait);
up_read(&h_sb->s_umount);
lockdep_on();
return err;
}
/* ---------------------------------------------------------------------- */
struct file *vfsub_dentry_open(struct path *path, int flags) struct file *vfsub_dentry_open(struct path *path, int flags)
{ {
struct file *file; struct file *file;
......
...@@ -37,6 +37,10 @@ enum { ...@@ -37,6 +37,10 @@ enum {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
/* ---------------------------------------------------------------------- */
struct file *vfsub_dentry_open(struct path *path, int flags); struct file *vfsub_dentry_open(struct path *path, int flags);
struct file *vfsub_filp_open(const char *path, int oflags, int mode); struct file *vfsub_filp_open(const char *path, int oflags, int mode);
int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment