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; struct au_sbinfo *sbinfo; SiMustWriteLock(sb); err = 0; dir = d_inode(sb->s_root); sbinfo = au_sbi(sb); opt_xino = NULL; opt = opts->opt; while (err >= 0 && opt->type != Opt_tail) { err = au_opt_simple(sb, opt, opts); if (!err) err = au_opt_br(sb, opt, opts); if (!err) err = au_opt_xino(sb, opt, &opt_xino, opts); opt++; } if (err > 0) err = 0; 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)) err = rerr; } /* will be handled by the caller */ if (!au_ftest_opts(opts->flags, REFRESH) && (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); return err; }
int au_opts_mount(struct super_block *sb, struct au_opts *opts) { int err; unsigned int tmp; aufs_bindex_t bindex, bend; struct au_opt *opt; struct au_opt_xino *opt_xino, xino; struct au_sbinfo *sbinfo; struct au_branch *br; SiMustWriteLock(sb); err = 0; opt_xino = NULL; opt = opts->opt; while (err >= 0 && opt->type != Opt_tail) err = au_opt_simple(sb, opt++, opts); if (err > 0) err = 0; else if (unlikely(err < 0)) goto out; /* disable xino and udba temporary */ sbinfo = au_sbi(sb); tmp = sbinfo->si_mntflags; au_opt_clr(sbinfo->si_mntflags, XINO); au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); opt = opts->opt; while (err >= 0 && opt->type != Opt_tail) err = au_opt_br(sb, opt++, opts); if (err > 0) err = 0; else if (unlikely(err < 0)) goto out; bend = au_sbend(sb); if (unlikely(bend < 0)) { err = -EINVAL; pr_err("no branches\n"); goto out; } if (au_opt_test(tmp, XINO)) au_opt_set(sbinfo->si_mntflags, XINO); opt = opts->opt; while (!err && opt->type != Opt_tail) err = au_opt_xino(sb, opt++, &opt_xino, opts); if (unlikely(err)) goto out; err = au_opts_verify(sb, sb->s_flags, tmp); if (unlikely(err)) goto out; /* restore xino */ if (au_opt_test(tmp, XINO) && !opt_xino) { xino.file = au_xino_def(sb); err = PTR_ERR(xino.file); if (IS_ERR(xino.file)) goto out; err = au_xino_set(sb, &xino, /*remount*/0); fput(xino.file); if (unlikely(err)) goto out; } /* restore udba */ tmp &= AuOptMask_UDBA; sbinfo->si_mntflags &= ~AuOptMask_UDBA; sbinfo->si_mntflags |= tmp; bend = au_sbend(sb); for (bindex = 0; bindex <= bend; bindex++) { br = au_sbr(sb, bindex); err = au_hnotify_reset_br(tmp, br, br->br_perm); if (unlikely(err)) AuIOErr("hnotify failed on br %d, %d, ignored\n", bindex, err); /* go on even if err */ } if (au_opt_test(tmp, UDBA_HNOTIFY)) { struct inode *dir = sb->s_root->d_inode; au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); } out: return err; }