Commit 4541724e authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: statfs sum options



Since aufs can have multiple writable branches, these options are
useful.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 0b7972a4
...@@ -29,6 +29,7 @@ enum { ...@@ -29,6 +29,7 @@ enum {
Opt_dio, Opt_nodio, Opt_dio, Opt_nodio,
Opt_wbr_copyup, Opt_wbr_create, Opt_wbr_copyup, Opt_wbr_create,
Opt_verbose, Opt_noverbose, Opt_verbose, Opt_noverbose,
Opt_sum, Opt_nosum, Opt_wsum,
Opt_dirperm1, Opt_nodirperm1, Opt_dirperm1, Opt_nodirperm1,
Opt_acl, Opt_noacl, Opt_acl, Opt_noacl,
Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
...@@ -94,6 +95,10 @@ static match_table_t options = { ...@@ -94,6 +95,10 @@ static match_table_t options = {
{Opt_noverbose, "q"}, {Opt_noverbose, "q"},
{Opt_noverbose, "silent"}, {Opt_noverbose, "silent"},
{Opt_sum, "sum"},
{Opt_nosum, "nosum"},
{Opt_wsum, "wsum"},
{Opt_rdcache, "rdcache=%d"}, {Opt_rdcache, "rdcache=%d"},
{Opt_rdblk, "rdblk=%d"}, {Opt_rdblk, "rdblk=%d"},
{Opt_rdblk_def, "rdblk=def"}, {Opt_rdblk_def, "rdblk=def"},
...@@ -593,6 +598,15 @@ static void dump_opts(struct au_opts *opts) ...@@ -593,6 +598,15 @@ static void dump_opts(struct au_opts *opts)
case Opt_noverbose: case Opt_noverbose:
AuLabel(noverbose); AuLabel(noverbose);
break; break;
case Opt_sum:
AuLabel(sum);
break;
case Opt_nosum:
AuLabel(nosum);
break;
case Opt_wsum:
AuLabel(wsum);
break;
case Opt_wbr_create: case Opt_wbr_create:
u.create = &opt->wbr_create; u.create = &opt->wbr_create;
AuDbg("create %d, %s\n", u.create->wbr_create, AuDbg("create %d, %s\n", u.create->wbr_create,
...@@ -1059,6 +1073,9 @@ int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) ...@@ -1059,6 +1073,9 @@ int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
case Opt_nodio: case Opt_nodio:
case Opt_verbose: case Opt_verbose:
case Opt_noverbose: case Opt_noverbose:
case Opt_sum:
case Opt_nosum:
case Opt_wsum:
case Opt_rdblk_def: case Opt_rdblk_def:
case Opt_rdhash_def: case Opt_rdhash_def:
case Opt_acl: case Opt_acl:
...@@ -1220,6 +1237,17 @@ static int au_opt_simple(struct super_block *sb, struct au_opt *opt, ...@@ -1220,6 +1237,17 @@ static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
au_opt_clr(sbinfo->si_mntflags, VERBOSE); au_opt_clr(sbinfo->si_mntflags, VERBOSE);
break; break;
case Opt_sum:
au_opt_set(sbinfo->si_mntflags, SUM);
break;
case Opt_wsum:
au_opt_clr(sbinfo->si_mntflags, SUM);
au_opt_set(sbinfo->si_mntflags, SUM_W);
case Opt_nosum:
au_opt_clr(sbinfo->si_mntflags, SUM);
au_opt_clr(sbinfo->si_mntflags, SUM_W);
break;
case Opt_wbr_create: case Opt_wbr_create:
err = au_opt_wbr_create(sb, &opt->wbr_create); err = au_opt_wbr_create(sb, &opt->wbr_create);
break; break;
......
...@@ -28,6 +28,8 @@ struct file; ...@@ -28,6 +28,8 @@ struct file;
#define AuOpt_PLINK (1 << 6) /* pseudo-link */ #define AuOpt_PLINK (1 << 6) /* pseudo-link */
#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm #define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
bits */ bits */
#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
#define AuOpt_SUM_W (1 << 11) /* unimplemented */
#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ #define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
#define AuOpt_DIO (1 << 14) /* direct io */ #define AuOpt_DIO (1 << 14) /* direct io */
......
...@@ -276,6 +276,8 @@ static int aufs_show_options(struct seq_file *m, struct dentry *dentry) ...@@ -276,6 +276,8 @@ static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
AuBool(SUM, sum);
/* AuBool(SUM_W, wsum); */
AuBool(VERBOSE, verbose); AuBool(VERBOSE, verbose);
out: out:
...@@ -294,6 +296,98 @@ out: ...@@ -294,6 +296,98 @@ out:
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* sum mode which returns the summation for statfs(2) */
static u64 au_add_till_max(u64 a, u64 b)
{
u64 old;
old = a;
a += b;
if (old <= a)
return a;
return ULLONG_MAX;
}
static u64 au_mul_till_max(u64 a, long mul)
{
u64 old;
old = a;
a *= mul;
if (old <= a)
return a;
return ULLONG_MAX;
}
static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
{
int err;
long bsize, factor;
u64 blocks, bfree, bavail, files, ffree;
aufs_bindex_t bbot, bindex, i;
unsigned char shared;
struct path h_path;
struct super_block *h_sb;
err = 0;
bsize = LONG_MAX;
files = 0;
ffree = 0;
blocks = 0;
bfree = 0;
bavail = 0;
bbot = au_sbbot(sb);
for (bindex = 0; bindex <= bbot; bindex++) {
h_path.mnt = au_sbr_mnt(sb, bindex);
h_sb = h_path.mnt->mnt_sb;
shared = 0;
for (i = 0; !shared && i < bindex; i++)
shared = (au_sbr_sb(sb, i) == h_sb);
if (shared)
continue;
/* sb->s_root for NFS is unreliable */
h_path.dentry = h_path.mnt->mnt_root;
err = vfs_statfs(&h_path, buf);
if (unlikely(err))
goto out;
if (bsize > buf->f_bsize) {
/*
* we will reduce bsize, so we have to expand blocks
* etc. to match them again
*/
factor = (bsize / buf->f_bsize);
blocks = au_mul_till_max(blocks, factor);
bfree = au_mul_till_max(bfree, factor);
bavail = au_mul_till_max(bavail, factor);
bsize = buf->f_bsize;
}
factor = (buf->f_bsize / bsize);
blocks = au_add_till_max(blocks,
au_mul_till_max(buf->f_blocks, factor));
bfree = au_add_till_max(bfree,
au_mul_till_max(buf->f_bfree, factor));
bavail = au_add_till_max(bavail,
au_mul_till_max(buf->f_bavail, factor));
files = au_add_till_max(files, buf->f_files);
ffree = au_add_till_max(ffree, buf->f_ffree);
}
buf->f_bsize = bsize;
buf->f_blocks = blocks;
buf->f_bfree = bfree;
buf->f_bavail = bavail;
buf->f_files = files;
buf->f_ffree = ffree;
buf->f_frsize = 0;
out:
return err;
}
static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
int err; int err;
...@@ -303,10 +397,13 @@ static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -303,10 +397,13 @@ static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
/* lock free root dinfo */ /* lock free root dinfo */
sb = dentry->d_sb; sb = dentry->d_sb;
si_noflush_read_lock(sb); si_noflush_read_lock(sb);
if (!au_opt_test(au_mntflags(sb), SUM)) {
/* sb->s_root for NFS is unreliable */ /* sb->s_root for NFS is unreliable */
h_path.mnt = au_sbr_mnt(sb, 0); h_path.mnt = au_sbr_mnt(sb, 0);
h_path.dentry = h_path.mnt->mnt_root; h_path.dentry = h_path.mnt->mnt_root;
err = vfs_statfs(&h_path, buf); err = vfs_statfs(&h_path, buf);
} else
err = au_statfs_sum(sb, buf);
si_read_unlock(sb); si_read_unlock(sb);
if (!err) { if (!err) {
......
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