summaryrefslogtreecommitdiff
path: root/fs/aufs/super.c
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-12-15 14:52:16 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-12-15 14:52:16 -0300
commit8d91c1e411f55d7ea91b1183a2e9f8088fb4d5be (patch)
treee9891aa6c295060d065adffd610c4f49ecf884f3 /fs/aufs/super.c
parenta71852147516bc1cb5b0b3cbd13639bfd4022dc8 (diff)
Linux-libre 4.3.2-gnu
Diffstat (limited to 'fs/aufs/super.c')
-rw-r--r--fs/aufs/super.c95
1 files changed, 69 insertions, 26 deletions
diff --git a/fs/aufs/super.c b/fs/aufs/super.c
index 7ae6ea12e..3fe10d35d 100644
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
@@ -93,13 +93,13 @@ static int au_show_brs(struct seq_file *seq, struct super_block *sb)
err = au_seq_path(seq, &path);
if (!err) {
au_optstr_br_perm(&perm, br->br_perm);
- err = seq_printf(seq, "=%s", perm.a);
- if (err == -1)
- err = -E2BIG;
+ seq_printf(seq, "=%s", perm.a);
+ if (bindex != bend)
+ seq_putc(seq, ':');
}
- if (!err && bindex != bend)
- err = seq_putc(seq, ':');
}
+ if (unlikely(err || seq_has_overflowed(seq)))
+ err = -E2BIG;
return err;
}
@@ -466,7 +466,8 @@ void au_array_free(void *array)
}
}
-void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
+ struct super_block *sb, void *arg)
{
void *array;
unsigned long long n, sz;
@@ -491,7 +492,7 @@ void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
goto out;
}
- n = cb(array, *hint, arg);
+ n = cb(sb, array, *hint, arg);
AuDebugOn(n > *hint);
out:
@@ -499,7 +500,7 @@ out:
return array;
}
-static unsigned long long au_iarray_cb(void *a,
+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
unsigned long long max __maybe_unused,
void *arg)
{
@@ -510,7 +511,7 @@ static unsigned long long au_iarray_cb(void *a,
n = 0;
p = a;
head = arg;
- spin_lock(&inode_sb_list_lock);
+ spin_lock(&sb->s_inode_list_lock);
list_for_each_entry(inode, head, i_sb_list) {
if (!is_bad_inode(inode)
&& au_ii(inode)->ii_bstart >= 0) {
@@ -524,7 +525,7 @@ static unsigned long long au_iarray_cb(void *a,
spin_unlock(&inode->i_lock);
}
}
- spin_unlock(&inode_sb_list_lock);
+ spin_unlock(&sb->s_inode_list_lock);
return n;
}
@@ -532,7 +533,7 @@ static unsigned long long au_iarray_cb(void *a,
struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
{
*max = atomic_long_read(&au_sbi(sb)->si_ninodes);
- return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
}
void au_iarray_free(struct inode **a, unsigned long long max)
@@ -568,7 +569,7 @@ static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
struct au_sbinfo *sbinfo,
- const unsigned int dir_flags)
+ const unsigned int dir_flags, unsigned int do_idop)
{
int err;
struct dentry *parent;
@@ -591,11 +592,17 @@ static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
}
dput(parent);
+ if (!err) {
+ if (do_idop)
+ au_refresh_dop(dentry, /*force_reval*/0);
+ } else
+ au_refresh_dop(dentry, /*force_reval*/1);
+
AuTraceErr(err);
return err;
}
-static int au_refresh_d(struct super_block *sb)
+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
{
int err, i, j, ndentry, e;
unsigned int sigen;
@@ -606,6 +613,9 @@ static int au_refresh_d(struct super_block *sb)
struct dentry *root = sb->s_root;
const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
+ if (do_idop)
+ au_refresh_dop(root, /*force_reval*/0);
+
err = au_dpages_init(&dpages, GFP_NOFS);
if (unlikely(err))
goto out;
@@ -621,7 +631,8 @@ static int au_refresh_d(struct super_block *sb)
ndentry = dpage->ndentry;
for (j = 0; j < ndentry; j++) {
d = dentries[j];
- e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
+ do_idop);
if (unlikely(e && !err))
err = e;
/* go on even err */
@@ -634,7 +645,7 @@ out:
return err;
}
-static int au_refresh_i(struct super_block *sb)
+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
{
int err, e;
unsigned int sigen;
@@ -652,17 +663,22 @@ static int au_refresh_i(struct super_block *sb)
inode = array[ull];
if (unlikely(!inode))
break;
+
+ e = 0;
+ ii_write_lock_child(inode);
if (au_iigen(inode, NULL) != sigen) {
- ii_write_lock_child(inode);
e = au_refresh_hinode_self(inode);
- ii_write_unlock(inode);
if (unlikely(e)) {
+ au_refresh_iop(inode, /*force_getattr*/1);
pr_err("error %d, i%lu\n", e, inode->i_ino);
if (!err)
err = e;
/* go on even if err */
}
}
+ if (!e && do_idop)
+ au_refresh_iop(inode, /*force_getattr*/0);
+ ii_write_unlock(inode);
}
au_iarray_free(array, max);
@@ -671,7 +687,7 @@ out:
return err;
}
-static void au_remount_refresh(struct super_block *sb)
+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
{
int err, e;
unsigned int udba;
@@ -679,9 +695,11 @@ static void au_remount_refresh(struct super_block *sb)
struct dentry *root;
struct inode *inode;
struct au_branch *br;
+ struct au_sbinfo *sbi;
au_sigen_inc(sb);
- au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
+ sbi = au_sbi(sb);
+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
root = sb->s_root;
DiMustNoWaiters(root);
@@ -700,9 +718,25 @@ static void au_remount_refresh(struct super_block *sb)
}
au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
+ if (do_idop) {
+ if (au_ftest_si(sbi, NO_DREVAL)) {
+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
+ sb->s_d_op = &aufs_dop_noreval;
+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
+ sbi->si_iop_array = aufs_iop_nogetattr;
+ } else {
+ AuDebugOn(sb->s_d_op == &aufs_dop);
+ sb->s_d_op = &aufs_dop;
+ AuDebugOn(sbi->si_iop_array == aufs_iop);
+ sbi->si_iop_array = aufs_iop;
+ }
+ pr_info("reset to %pf and %pf\n",
+ sb->s_d_op, sbi->si_iop_array);
+ }
+
di_write_unlock(root);
- err = au_refresh_d(sb);
- e = au_refresh_i(sb);
+ err = au_refresh_d(sb, do_idop);
+ e = au_refresh_i(sb, do_idop);
if (unlikely(e && !err))
err = e;
/* aufs_write_lock() calls ..._child() */
@@ -777,7 +811,7 @@ static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
au_opts_free(&opts);
if (au_ftest_opts(opts.flags, REFRESH))
- au_remount_refresh(sb);
+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
mntflags = au_mntflags(sb);
@@ -824,7 +858,7 @@ static int alloc_root(struct super_block *sb)
if (IS_ERR(inode))
goto out;
- inode->i_op = &aufs_dir_iop;
+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
inode->i_fop = &aufs_dir_fop;
inode->i_mode = S_IFDIR;
set_nlink(inode, 2);
@@ -853,6 +887,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
{
int err;
struct au_opts opts;
+ struct au_sbinfo *sbinfo;
struct dentry *root;
struct inode *inode;
char *arg = raw_data;
@@ -874,6 +909,7 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
err = au_si_alloc(sb);
if (unlikely(err))
goto out_opts;
+ sbinfo = au_sbi(sb);
/* all timestamps always follow the ones on the branch */
sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
@@ -909,6 +945,13 @@ static int aufs_fill_super(struct super_block *sb, void *raw_data,
aufs_write_lock(root);
err = au_opts_mount(sb, &opts);
au_opts_free(&opts);
+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
+ sb->s_d_op = &aufs_dop_noreval;
+ pr_info("%pf\n", sb->s_d_op);
+ au_refresh_dop(root, /*force_reval*/0);
+ sbinfo->si_iop_array = aufs_iop_nogetattr;
+ au_refresh_iop(inode, /*force_getattr*/0);
+ }
aufs_write_unlock(root);
mutex_unlock(&inode->i_mutex);
if (!err)
@@ -918,8 +961,8 @@ out_root:
dput(root);
sb->s_root = NULL;
out_info:
- dbgaufs_si_fin(au_sbi(sb));
- kobject_put(&au_sbi(sb)->si_kobj);
+ dbgaufs_si_fin(sbinfo);
+ kobject_put(&sbinfo->si_kobj);
sb->s_fs_info = NULL;
out_opts:
free_page((unsigned long)opts.opt);
@@ -968,7 +1011,7 @@ static void aufs_kill_sb(struct super_block *sb)
sbinfo->si_wbr_create_ops->fin(sb);
if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
- au_remount_refresh(sb);
+ au_remount_refresh(sb, /*do_idop*/0);
}
if (au_opt_test(sbinfo->si_mntflags, PLINK))
au_plink_put(sb, /*verbose*/1);