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; }
/* * returns tri-state. * plus: processed without an error * zero: unprocessed * minus: error */ static int au_opt_br(struct super_block *sb, struct au_opt *opt, struct au_opts *opts) { int err, do_refresh; err = 0; switch (opt->type) { case Opt_append: opt->add.bindex = au_sbend(sb) + 1; if (opt->add.bindex < 0) opt->add.bindex = 0; goto add; case Opt_prepend: opt->add.bindex = 0; add: case Opt_add: err = au_br_add(sb, &opt->add, au_ftest_opts(opts->flags, REMOUNT)); if (!err) { err = 1; au_fset_opts(opts->flags, REFRESH); } break; case Opt_del: case Opt_idel: err = au_br_del(sb, &opt->del, au_ftest_opts(opts->flags, REMOUNT)); if (!err) { err = 1; au_fset_opts(opts->flags, TRUNC_XIB); au_fset_opts(opts->flags, REFRESH); } break; case Opt_mod: case Opt_imod: err = au_br_mod(sb, &opt->mod, au_ftest_opts(opts->flags, REMOUNT), &do_refresh); if (!err) { err = 1; if (do_refresh) au_fset_opts(opts->flags, REFRESH); } break; } return err; }
/* * returns, * plus: processed without an error * zero: unprocessed */ static int au_opt_simple(struct super_block *sb, struct au_opt *opt, struct au_opts *opts) { int err; struct au_sbinfo *sbinfo; SiMustWriteLock(sb); err = 1; /* handled */ sbinfo = au_sbi(sb); switch (opt->type) { case Opt_udba: sbinfo->si_mntflags &= ~AuOptMask_UDBA; sbinfo->si_mntflags |= opt->udba; opts->given_udba |= opt->udba; break; case Opt_plink: au_opt_set(sbinfo->si_mntflags, PLINK); break; case Opt_noplink: if (au_opt_test(sbinfo->si_mntflags, PLINK)) au_plink_put(sb, /*verbose*/1); au_opt_clr(sbinfo->si_mntflags, PLINK); break; case Opt_list_plink: if (au_opt_test(sbinfo->si_mntflags, PLINK)) au_plink_list(sb); break; case Opt_dio: au_opt_set(sbinfo->si_mntflags, DIO); au_fset_opts(opts->flags, REFRESH_DYAOP); break; case Opt_nodio: au_opt_clr(sbinfo->si_mntflags, DIO); au_fset_opts(opts->flags, REFRESH_DYAOP); break; case Opt_diropq_a: au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); break; case Opt_diropq_w: au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); break; case Opt_warn_perm: au_opt_set(sbinfo->si_mntflags, WARN_PERM); break; case Opt_nowarn_perm: au_opt_clr(sbinfo->si_mntflags, WARN_PERM); break; case Opt_refrof: au_opt_set(sbinfo->si_mntflags, REFROF); break; case Opt_norefrof: au_opt_clr(sbinfo->si_mntflags, REFROF); break; case Opt_verbose: au_opt_set(sbinfo->si_mntflags, VERBOSE); break; case Opt_noverbose: au_opt_clr(sbinfo->si_mntflags, VERBOSE); 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: err = au_opt_wbr_create(sb, &opt->wbr_create); break; case Opt_wbr_copyup: sbinfo->si_wbr_copyup = opt->wbr_copyup; sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; break; case Opt_dirwh: sbinfo->si_dirwh = opt->dirwh; break; case Opt_rdcache: sbinfo->si_rdcache = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); break; case Opt_rdblk: sbinfo->si_rdblk = opt->rdblk; break; case Opt_rdblk_def: sbinfo->si_rdblk = AUFS_RDBLK_DEF; break; case Opt_rdhash: sbinfo->si_rdhash = opt->rdhash; break; case Opt_rdhash_def: sbinfo->si_rdhash = AUFS_RDHASH_DEF; break; case Opt_shwh: au_opt_set(sbinfo->si_mntflags, SHWH); break; case Opt_noshwh: au_opt_clr(sbinfo->si_mntflags, SHWH); break; case Opt_trunc_xino: au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); break; case Opt_notrunc_xino: au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); break; case Opt_trunc_xino_path: case Opt_itrunc_xino: err = au_xino_trunc(sb, opt->xino_itrunc.bindex); if (!err) err = 1; break; case Opt_trunc_xib: au_fset_opts(opts->flags, TRUNC_XIB); break; case Opt_notrunc_xib: au_fclr_opts(opts->flags, TRUNC_XIB); break; default: err = 0; break; } return err; }