diff options
Diffstat (limited to 'fs/aufs/opts.c')
-rw-r--r-- | fs/aufs/opts.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c index 90098fe7f..f79d15e32 100644 --- a/fs/aufs/opts.c +++ b/fs/aufs/opts.c @@ -1555,10 +1555,10 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, { int err, fhsm; aufs_bindex_t bindex, bend; - unsigned char do_plink, skip, do_free; + unsigned char do_plink, skip, do_free, can_no_dreval; struct au_branch *br; struct au_wbr *wbr; - struct dentry *root; + struct dentry *root, *dentry; struct inode *dir, *h_dir; struct au_sbinfo *sbinfo; struct au_hinode *hdir; @@ -1588,6 +1588,8 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, root = sb->s_root; dir = d_inode(root); do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); + can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), + UDBA_NONE); bend = au_sbend(sb); for (bindex = 0; !err && bindex <= bend; bindex++) { skip = 0; @@ -1636,6 +1638,15 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, if (wbr) wbr_wh_read_unlock(wbr); + if (can_no_dreval) { + dentry = br->br_path.dentry; + spin_lock(&dentry->d_lock); + if (dentry->d_flags & + (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) + can_no_dreval = 0; + spin_unlock(&dentry->d_lock); + } + if (au_br_fhsm(br->br_perm)) { fhsm++; AuDebugOn(!br->br_fhsm); @@ -1659,6 +1670,11 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, } } + if (can_no_dreval) + au_fset_si(sbinfo, NO_DREVAL); + else + au_fclr_si(sbinfo, NO_DREVAL); + if (fhsm >= 2) { au_fset_si(sbinfo, FHSM); for (bindex = bend; bindex >= 0; bindex--) { @@ -1770,6 +1786,7 @@ out: int au_opts_remount(struct super_block *sb, struct au_opts *opts) { int err, rerr; + unsigned char no_dreval; struct inode *dir; struct au_opt_xino *opt_xino; struct au_opt *opt; @@ -1777,9 +1794,9 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts) SiMustWriteLock(sb); + err = 0; dir = d_inode(sb->s_root); sbinfo = au_sbi(sb); - err = 0; opt_xino = NULL; opt = opts->opt; while (err >= 0 && opt->type != Opt_tail) { @@ -1795,10 +1812,14 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts) AuTraceErr(err); /* go on even err */ + no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); if (unlikely(rerr && !err)) err = rerr; + if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) + au_fset_opts(opts->flags, REFRESH_IDOP); + if (au_ftest_opts(opts->flags, TRUNC_XIB)) { rerr = au_xib_trunc(sb); if (unlikely(rerr && !err)) @@ -1807,7 +1828,10 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts) /* will be handled by the caller */ if (!au_ftest_opts(opts->flags, REFRESH) - && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO))) + && (opts->given_udba + || au_opt_test(sbinfo->si_mntflags, XINO) + || au_ftest_opts(opts->flags, REFRESH_IDOP) + )) au_fset_opts(opts->flags, REFRESH); AuDbg("status 0x%x\n", opts->flags); |