2 * Copyright (C) 2005-2010 Junjiro R. Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <linux/file.h>
24 #include <linux/namei.h>
25 #include <linux/types.h> /* a distribution requires */
26 #include <linux/parser.h>
29 /* ---------------------------------------------------------------------- */
33 Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
34 Opt_idel, Opt_imod, Opt_ireorder,
35 Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
36 Opt_rdblk_def, Opt_rdhash_def,
37 Opt_xino, Opt_zxino, Opt_noxino,
38 Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
39 Opt_trunc_xino_path, Opt_itrunc_xino,
40 Opt_trunc_xib, Opt_notrunc_xib,
42 Opt_plink, Opt_noplink, Opt_list_plink,
45 /* Opt_lock, Opt_unlock, */
46 Opt_cmd, Opt_cmd_args,
47 Opt_diropq_a, Opt_diropq_w,
48 Opt_warn_perm, Opt_nowarn_perm,
49 Opt_wbr_copyup, Opt_wbr_create,
50 Opt_refrof, Opt_norefrof,
51 Opt_verbose, Opt_noverbose,
52 Opt_sum, Opt_nosum, Opt_wsum,
53 Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
56 static match_table_t options = {
60 {Opt_add, "add=%d:%s"},
61 {Opt_add, "add:%d:%s"},
62 {Opt_add, "ins=%d:%s"},
63 {Opt_add, "ins:%d:%s"},
64 {Opt_append, "append=%s"},
65 {Opt_append, "append:%s"},
66 {Opt_prepend, "prepend=%s"},
67 {Opt_prepend, "prepend:%s"},
71 /* {Opt_idel, "idel:%d"}, */
74 /* {Opt_imod, "imod:%d:%s"}, */
76 {Opt_dirwh, "dirwh=%d"},
78 {Opt_xino, "xino=%s"},
79 {Opt_noxino, "noxino"},
80 {Opt_trunc_xino, "trunc_xino"},
81 {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
82 {Opt_notrunc_xino, "notrunc_xino"},
83 {Opt_trunc_xino_path, "trunc_xino=%s"},
84 {Opt_itrunc_xino, "itrunc_xino=%d"},
85 /* {Opt_zxino, "zxino=%s"}, */
86 {Opt_trunc_xib, "trunc_xib"},
87 {Opt_notrunc_xib, "notrunc_xib"},
90 {Opt_noplink, "noplink"},
91 #ifdef CONFIG_AUFS_DEBUG
92 {Opt_list_plink, "list_plink"},
95 {Opt_udba, "udba=%s"},
100 {Opt_diropq_a, "diropq=always"},
101 {Opt_diropq_a, "diropq=a"},
102 {Opt_diropq_w, "diropq=whiteouted"},
103 {Opt_diropq_w, "diropq=w"},
105 {Opt_warn_perm, "warn_perm"},
106 {Opt_nowarn_perm, "nowarn_perm"},
108 /* keep them temporary */
109 {Opt_ignore_silent, "coo=%s"},
110 {Opt_ignore_silent, "nodlgt"},
111 {Opt_ignore_silent, "nodirperm1"},
112 {Opt_ignore_silent, "clean_plink"},
114 #ifdef CONFIG_AUFS_SHWH
117 {Opt_noshwh, "noshwh"},
119 {Opt_rendir, "rendir=%d"},
121 {Opt_refrof, "refrof"},
122 {Opt_norefrof, "norefrof"},
124 {Opt_verbose, "verbose"},
126 {Opt_noverbose, "noverbose"},
127 {Opt_noverbose, "quiet"},
128 {Opt_noverbose, "q"},
129 {Opt_noverbose, "silent"},
132 {Opt_nosum, "nosum"},
135 {Opt_rdcache, "rdcache=%d"},
136 {Opt_rdblk, "rdblk=%d"},
137 {Opt_rdblk_def, "rdblk=def"},
138 {Opt_rdhash, "rdhash=%d"},
139 {Opt_rdhash_def, "rdhash=def"},
141 {Opt_wbr_create, "create=%s"},
142 {Opt_wbr_create, "create_policy=%s"},
143 {Opt_wbr_copyup, "cpup=%s"},
144 {Opt_wbr_copyup, "copyup=%s"},
145 {Opt_wbr_copyup, "copyup_policy=%s"},
147 /* internal use for the scripts */
148 {Opt_ignore_silent, "si=%s"},
151 {Opt_ignore, "debug=%d"},
152 {Opt_ignore, "delete=whiteout"},
153 {Opt_ignore, "delete=all"},
154 {Opt_ignore, "imap=%s"},
156 /* temporary workaround, due to old mount(8)? */
157 {Opt_ignore_silent, "relatime"},
162 /* ---------------------------------------------------------------------- */
164 static const char *au_parser_pattern(int val, struct match_token *token)
166 while (token->pattern) {
167 if (token->token == val)
168 return token->pattern;
175 /* ---------------------------------------------------------------------- */
177 static match_table_t brperms = {
178 {AuBrPerm_RO, AUFS_BRPERM_RO},
179 {AuBrPerm_RR, AUFS_BRPERM_RR},
180 {AuBrPerm_RW, AUFS_BRPERM_RW},
182 {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
183 {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
184 {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
186 {AuBrPerm_ROWH, "nfsro"},
190 static int noinline_for_stack br_perm_val(char *perm)
193 substring_t args[MAX_OPT_ARGS];
195 val = match_token(perm, brperms, args);
199 const char *au_optstr_br_perm(int brperm)
201 return au_parser_pattern(brperm, (void *)brperms);
204 /* ---------------------------------------------------------------------- */
206 static match_table_t udbalevel = {
207 {AuOpt_UDBA_REVAL, "reval"},
208 {AuOpt_UDBA_NONE, "none"},
209 #ifdef CONFIG_AUFS_HNOTIFY
210 {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
211 #ifdef CONFIG_AUFS_HFSNOTIFY
212 {AuOpt_UDBA_HNOTIFY, "fsnotify"},
214 {AuOpt_UDBA_HNOTIFY, "inotify"},
220 static void au_warn_inotify(int val, char *str)
222 #ifdef CONFIG_AUFS_HINOTIFY
223 if (val == AuOpt_UDBA_HNOTIFY
224 && !strcmp(str, "inotify"))
225 AuWarn1("udba=inotify is deprecated, use udba=notify\n");
229 static int noinline_for_stack udba_val(char *str)
232 substring_t args[MAX_OPT_ARGS];
234 val = match_token(str, udbalevel, args);
235 au_warn_inotify(val, str);
239 const char *au_optstr_udba(int udba)
241 return au_parser_pattern(udba, (void *)udbalevel);
244 /* ---------------------------------------------------------------------- */
246 static match_table_t au_wbr_create_policy = {
247 {AuWbrCreate_TDP, "tdp"},
248 {AuWbrCreate_TDP, "top-down-parent"},
249 {AuWbrCreate_RR, "rr"},
250 {AuWbrCreate_RR, "round-robin"},
251 {AuWbrCreate_MFS, "mfs"},
252 {AuWbrCreate_MFS, "most-free-space"},
253 {AuWbrCreate_MFSV, "mfs:%d"},
254 {AuWbrCreate_MFSV, "most-free-space:%d"},
256 {AuWbrCreate_MFSRR, "mfsrr:%d"},
257 {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
258 {AuWbrCreate_PMFS, "pmfs"},
259 {AuWbrCreate_PMFSV, "pmfs:%d"},
265 * cf. linux/lib/parser.c and cmdline.c
266 * gave up calling memparse() since it uses simple_strtoull() instead of
269 static int noinline_for_stack
270 au_match_ull(substring_t *s, unsigned long long *result)
277 len = s->to - s->from;
278 if (len + 1 <= sizeof(a)) {
279 memcpy(a, s->from, len);
281 err = strict_strtoull(a, 0, result);
286 static int au_wbr_mfs_wmark(substring_t *arg, char *str,
287 struct au_opt_wbr_create *create)
290 unsigned long long ull;
293 if (!au_match_ull(arg, &ull))
294 create->mfsrr_watermark = ull;
296 pr_err("bad integer in %s\n", str);
303 static int au_wbr_mfs_sec(substring_t *arg, char *str,
304 struct au_opt_wbr_create *create)
309 if (!match_int(arg, &n) && 0 <= n)
310 create->mfs_second = n;
312 pr_err("bad integer in %s\n", str);
319 static int noinline_for_stack
320 au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
323 substring_t args[MAX_OPT_ARGS];
325 err = match_token(str, au_wbr_create_policy, args);
326 create->wbr_create = err;
328 case AuWbrCreate_MFSRRV:
329 e = au_wbr_mfs_wmark(&args[0], str, create);
331 e = au_wbr_mfs_sec(&args[1], str, create);
335 case AuWbrCreate_MFSRR:
336 e = au_wbr_mfs_wmark(&args[0], str, create);
342 case AuWbrCreate_MFS:
343 case AuWbrCreate_PMFS:
344 create->mfs_second = AUFS_MFS_SECOND_DEF;
346 case AuWbrCreate_MFSV:
347 case AuWbrCreate_PMFSV:
348 e = au_wbr_mfs_sec(&args[0], str, create);
357 const char *au_optstr_wbr_create(int wbr_create)
359 return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
362 static match_table_t au_wbr_copyup_policy = {
363 {AuWbrCopyup_TDP, "tdp"},
364 {AuWbrCopyup_TDP, "top-down-parent"},
365 {AuWbrCopyup_BUP, "bup"},
366 {AuWbrCopyup_BUP, "bottom-up-parent"},
367 {AuWbrCopyup_BU, "bu"},
368 {AuWbrCopyup_BU, "bottom-up"},
372 static int noinline_for_stack au_wbr_copyup_val(char *str)
374 substring_t args[MAX_OPT_ARGS];
376 return match_token(str, au_wbr_copyup_policy, args);
379 const char *au_optstr_wbr_copyup(int wbr_copyup)
381 return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
384 /* ---------------------------------------------------------------------- */
386 static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
388 static void dump_opts(struct au_opts *opts)
390 #ifdef CONFIG_AUFS_DEBUG
391 /* reduce stack space */
393 struct au_opt_add *add;
394 struct au_opt_del *del;
395 struct au_opt_mod *mod;
396 struct au_opt_xino *xino;
397 struct au_opt_xino_itrunc *xino_itrunc;
398 struct au_opt_wbr_create *create;
403 while (opt->type != Opt_tail) {
407 AuDbg("add {b%d, %s, 0x%x, %p}\n",
408 u.add->bindex, u.add->pathname, u.add->perm,
414 AuDbg("del {%s, %p}\n",
415 u.del->pathname, u.del->h_path.dentry);
420 AuDbg("mod {%s, 0x%x, %p}\n",
421 u.mod->path, u.mod->perm, u.mod->h_root);
425 AuDbg("append {b%d, %s, 0x%x, %p}\n",
426 u.add->bindex, u.add->pathname, u.add->perm,
431 AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
432 u.add->bindex, u.add->pathname, u.add->perm,
436 AuDbg("dirwh %d\n", opt->dirwh);
439 AuDbg("rdcache %d\n", opt->rdcache);
442 AuDbg("rdblk %u\n", opt->rdblk);
445 AuDbg("rdblk_def\n");
448 AuDbg("rdhash %u\n", opt->rdhash);
451 AuDbg("rdhash_def\n");
455 AuDbg("xino {%s %.*s}\n",
457 AuDLNPair(u.xino->file->f_dentry));
462 case Opt_notrunc_xino:
463 AuLabel(notrunc_xino);
465 case Opt_trunc_xino_path:
466 case Opt_itrunc_xino:
467 u.xino_itrunc = &opt->xino_itrunc;
468 AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
477 case Opt_notrunc_xib:
478 AuLabel(notrunc_xib);
496 AuDbg("udba %d, %s\n",
497 opt->udba, au_optstr_udba(opt->udba));
514 case Opt_nowarn_perm:
515 AuLabel(nowarn_perm);
539 u.create = &opt->wbr_create;
540 AuDbg("create %d, %s\n", u.create->wbr_create,
541 au_optstr_wbr_create(u.create->wbr_create));
542 switch (u.create->wbr_create) {
543 case AuWbrCreate_MFSV:
544 case AuWbrCreate_PMFSV:
545 AuDbg("%d sec\n", u.create->mfs_second);
547 case AuWbrCreate_MFSRR:
548 AuDbg("%llu watermark\n",
549 u.create->mfsrr_watermark);
551 case AuWbrCreate_MFSRRV:
552 AuDbg("%llu watermark, %d sec\n",
553 u.create->mfsrr_watermark,
554 u.create->mfs_second);
559 AuDbg("copyup %d, %s\n", opt->wbr_copyup,
560 au_optstr_wbr_copyup(opt->wbr_copyup));
570 void au_opts_free(struct au_opts *opts)
575 while (opt->type != Opt_tail) {
580 path_put(&opt->add.path);
584 path_put(&opt->del.h_path);
588 dput(opt->mod.h_root);
591 fput(opt->xino.file);
598 static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
599 aufs_bindex_t bindex)
602 struct au_opt_add *add = &opt->add;
605 add->bindex = bindex;
606 add->perm = AuBrPerm_Last;
607 add->pathname = opt_str;
608 p = strchr(opt_str, '=');
612 add->perm = br_perm_val(p);
615 err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
618 add->perm = AuBrPerm_RO;
619 if (au_test_fs_rr(add->path.dentry->d_sb))
620 add->perm = AuBrPerm_RR;
621 else if (!bindex && !(sb_flags & MS_RDONLY))
622 add->perm = AuBrPerm_RW;
627 pr_err("lookup failed %s (%d)\n", add->pathname, err);
634 static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
638 del->pathname = args[0].from;
639 AuDbg("del path %s\n", del->pathname);
641 err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
643 pr_err("lookup failed %s (%d)\n", del->pathname, err);
648 #if 0 /* reserved for future use */
649 static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
650 struct au_opt_del *del, substring_t args[])
657 aufs_read_lock(root, AuLock_FLUSH);
658 if (bindex < 0 || au_sbend(sb) < bindex) {
659 pr_err("out of bounds, %d\n", bindex);
664 del->h_path.dentry = dget(au_h_dptr(root, bindex));
665 del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
668 aufs_read_unlock(root, !AuLock_IR);
673 static int noinline_for_stack
674 au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
681 mod->path = args[0].from;
682 p = strchr(mod->path, '=');
684 pr_err("no permssion %s\n", args[0].from);
689 err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
691 pr_err("lookup failed %s (%d)\n", mod->path, err);
695 mod->perm = br_perm_val(p);
696 AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
697 mod->h_root = dget(path.dentry);
704 #if 0 /* reserved for future use */
705 static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
706 struct au_opt_mod *mod, substring_t args[])
713 aufs_read_lock(root, AuLock_FLUSH);
714 if (bindex < 0 || au_sbend(sb) < bindex) {
715 pr_err("out of bounds, %d\n", bindex);
720 mod->perm = br_perm_val(args[1].from);
721 AuDbg("mod path %s, perm 0x%x, %s\n",
722 mod->path, mod->perm, args[1].from);
723 mod->h_root = dget(au_h_dptr(root, bindex));
726 aufs_read_unlock(root, !AuLock_IR);
731 static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
737 file = au_xino_create(sb, args[0].from, /*silent*/0);
743 if (unlikely(file->f_dentry->d_sb == sb)) {
745 pr_err("%s must be outside\n", args[0].from);
751 xino->path = args[0].from;
757 static int noinline_for_stack
758 au_opts_parse_xino_itrunc_path(struct super_block *sb,
759 struct au_opt_xino_itrunc *xino_itrunc,
763 aufs_bindex_t bend, bindex;
767 err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
769 pr_err("lookup failed %s (%d)\n", args[0].from, err);
773 xino_itrunc->bindex = -1;
775 aufs_read_lock(root, AuLock_FLUSH);
777 for (bindex = 0; bindex <= bend; bindex++) {
778 if (au_h_dptr(root, bindex) == path.dentry) {
779 xino_itrunc->bindex = bindex;
783 aufs_read_unlock(root, !AuLock_IR);
786 if (unlikely(xino_itrunc->bindex < 0)) {
787 pr_err("no such branch %s\n", args[0].from);
795 /* called without aufs lock */
796 int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
799 aufs_bindex_t bindex;
800 unsigned char skipped;
802 struct au_opt *opt, *opt_tail;
804 /* reduce the stack space */
806 struct au_opt_xino_itrunc *xino_itrunc;
807 struct au_opt_wbr_create *create;
810 substring_t args[MAX_OPT_ARGS];
814 a = kmalloc(sizeof(*a), GFP_NOFS);
822 opt_tail = opt + opts->max_opt - 1;
823 opt->type = Opt_tail;
824 while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
827 token = match_token(opt_str, options, a->args);
831 while (!err && (opt_str = strsep(&a->args[0].from, ":"))
833 err = opt_add(opt, opt_str, opts->sb_flags,
835 if (unlikely(!err && ++opt > opt_tail)) {
839 opt->type = Opt_tail;
844 if (unlikely(match_int(&a->args[0], &n))) {
845 pr_err("bad integer in %s\n", opt_str);
849 err = opt_add(opt, a->args[1].from, opts->sb_flags,
855 err = opt_add(opt, a->args[0].from, opts->sb_flags,
861 err = opt_add(opt, a->args[0].from, opts->sb_flags,
867 err = au_opts_parse_del(&opt->del, a->args);
871 #if 0 /* reserved for future use */
873 del->pathname = "(indexed)";
874 if (unlikely(match_int(&args[0], &n))) {
875 pr_err("bad integer in %s\n", opt_str);
878 err = au_opts_parse_idel(sb, n, &opt->del, a->args);
884 err = au_opts_parse_mod(&opt->mod, a->args);
888 #ifdef IMOD /* reserved for future use */
890 u.mod->path = "(indexed)";
891 if (unlikely(match_int(&a->args[0], &n))) {
892 pr_err("bad integer in %s\n", opt_str);
895 err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
901 err = au_opts_parse_xino(sb, &opt->xino, a->args);
906 case Opt_trunc_xino_path:
907 err = au_opts_parse_xino_itrunc_path
908 (sb, &opt->xino_itrunc, a->args);
913 case Opt_itrunc_xino:
914 u.xino_itrunc = &opt->xino_itrunc;
915 if (unlikely(match_int(&a->args[0], &n))) {
916 pr_err("bad integer in %s\n", opt_str);
919 u.xino_itrunc->bindex = n;
920 aufs_read_lock(root, AuLock_FLUSH);
921 if (n < 0 || au_sbend(sb) < n) {
922 pr_err("out of bounds, %d\n", n);
923 aufs_read_unlock(root, !AuLock_IR);
926 aufs_read_unlock(root, !AuLock_IR);
932 if (unlikely(match_int(&a->args[0], &opt->dirwh)))
939 if (unlikely(match_int(&a->args[0], &opt->rdcache)))
945 if (unlikely(match_int(&a->args[0], &n)
947 || n > KMALLOC_MAX_SIZE)) {
948 pr_err("bad integer in %s\n", opt_str);
951 if (unlikely(n && n < NAME_MAX)) {
952 pr_err("rdblk must be larger than %d\n",
961 if (unlikely(match_int(&a->args[0], &n)
963 || n * sizeof(struct hlist_head)
964 > KMALLOC_MAX_SIZE)) {
965 pr_err("bad integer in %s\n", opt_str);
974 case Opt_notrunc_xino:
977 case Opt_notrunc_xib:
988 case Opt_nowarn_perm:
1003 opt->udba = udba_val(a->args[0].from);
1004 if (opt->udba >= 0) {
1008 pr_err("wrong value, %s\n", opt_str);
1011 case Opt_wbr_create:
1012 u.create = &opt->wbr_create;
1013 u.create->wbr_create
1014 = au_wbr_create_val(a->args[0].from, u.create);
1015 if (u.create->wbr_create >= 0) {
1019 pr_err("wrong value, %s\n", opt_str);
1021 case Opt_wbr_copyup:
1022 opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
1023 if (opt->wbr_copyup >= 0) {
1027 pr_err("wrong value, %s\n", opt_str);
1031 pr_warning("ignored %s\n", opt_str);
1033 case Opt_ignore_silent:
1038 pr_err("unknown option %s\n", opt_str);
1042 if (!err && !skipped) {
1043 if (unlikely(++opt > opt_tail)) {
1046 opt->type = Opt_tail;
1049 opt->type = Opt_tail;
1062 static int au_opt_wbr_create(struct super_block *sb,
1063 struct au_opt_wbr_create *create)
1066 struct au_sbinfo *sbinfo;
1068 SiMustWriteLock(sb);
1070 err = 1; /* handled */
1071 sbinfo = au_sbi(sb);
1072 if (sbinfo->si_wbr_create_ops->fin) {
1073 err = sbinfo->si_wbr_create_ops->fin(sb);
1078 sbinfo->si_wbr_create = create->wbr_create;
1079 sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
1080 switch (create->wbr_create) {
1081 case AuWbrCreate_MFSRRV:
1082 case AuWbrCreate_MFSRR:
1083 sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
1085 case AuWbrCreate_MFS:
1086 case AuWbrCreate_MFSV:
1087 case AuWbrCreate_PMFS:
1088 case AuWbrCreate_PMFSV:
1089 sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
1093 if (sbinfo->si_wbr_create_ops->init)
1094 sbinfo->si_wbr_create_ops->init(sb); /* ignore */
1101 * plus: processed without an error
1104 static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
1105 struct au_opts *opts)
1108 struct au_sbinfo *sbinfo;
1110 SiMustWriteLock(sb);
1112 err = 1; /* handled */
1113 sbinfo = au_sbi(sb);
1114 switch (opt->type) {
1116 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1117 sbinfo->si_mntflags |= opt->udba;
1118 opts->given_udba |= opt->udba;
1122 au_opt_set(sbinfo->si_mntflags, PLINK);
1125 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1127 au_opt_clr(sbinfo->si_mntflags, PLINK);
1129 case Opt_list_plink:
1130 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1135 au_opt_set(sbinfo->si_mntflags, DIO);
1136 au_fset_opts(opts->flags, REFRESH_DYAOP);
1139 au_opt_clr(sbinfo->si_mntflags, DIO);
1140 au_fset_opts(opts->flags, REFRESH_DYAOP);
1144 au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1147 au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1151 au_opt_set(sbinfo->si_mntflags, WARN_PERM);
1153 case Opt_nowarn_perm:
1154 au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
1158 au_opt_set(sbinfo->si_mntflags, REFROF);
1161 au_opt_clr(sbinfo->si_mntflags, REFROF);
1165 au_opt_set(sbinfo->si_mntflags, VERBOSE);
1168 au_opt_clr(sbinfo->si_mntflags, VERBOSE);
1172 au_opt_set(sbinfo->si_mntflags, SUM);
1175 au_opt_clr(sbinfo->si_mntflags, SUM);
1176 au_opt_set(sbinfo->si_mntflags, SUM_W);
1178 au_opt_clr(sbinfo->si_mntflags, SUM);
1179 au_opt_clr(sbinfo->si_mntflags, SUM_W);
1182 case Opt_wbr_create:
1183 err = au_opt_wbr_create(sb, &opt->wbr_create);
1185 case Opt_wbr_copyup:
1186 sbinfo->si_wbr_copyup = opt->wbr_copyup;
1187 sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
1191 sbinfo->si_dirwh = opt->dirwh;
1195 sbinfo->si_rdcache = opt->rdcache * HZ;
1198 sbinfo->si_rdblk = opt->rdblk;
1201 sbinfo->si_rdblk = AUFS_RDBLK_DEF;
1204 sbinfo->si_rdhash = opt->rdhash;
1206 case Opt_rdhash_def:
1207 sbinfo->si_rdhash = AUFS_RDHASH_DEF;
1211 au_opt_set(sbinfo->si_mntflags, SHWH);
1214 au_opt_clr(sbinfo->si_mntflags, SHWH);
1217 case Opt_trunc_xino:
1218 au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
1220 case Opt_notrunc_xino:
1221 au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
1224 case Opt_trunc_xino_path:
1225 case Opt_itrunc_xino:
1226 err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
1232 au_fset_opts(opts->flags, TRUNC_XIB);
1234 case Opt_notrunc_xib:
1235 au_fclr_opts(opts->flags, TRUNC_XIB);
1247 * returns tri-state.
1248 * plus: processed without an error
1252 static int au_opt_br(struct super_block *sb, struct au_opt *opt,
1253 struct au_opts *opts)
1255 int err, do_refresh;
1258 switch (opt->type) {
1260 opt->add.bindex = au_sbend(sb) + 1;
1261 if (opt->add.bindex < 0)
1262 opt->add.bindex = 0;
1265 opt->add.bindex = 0;
1268 err = au_br_add(sb, &opt->add,
1269 au_ftest_opts(opts->flags, REMOUNT));
1272 au_fset_opts(opts->flags, REFRESH_DIR);
1273 au_fset_opts(opts->flags, REFRESH_NONDIR);
1279 err = au_br_del(sb, &opt->del,
1280 au_ftest_opts(opts->flags, REMOUNT));
1283 au_fset_opts(opts->flags, TRUNC_XIB);
1284 au_fset_opts(opts->flags, REFRESH_DIR);
1285 au_fset_opts(opts->flags, REFRESH_NONDIR);
1291 err = au_br_mod(sb, &opt->mod,
1292 au_ftest_opts(opts->flags, REMOUNT),
1297 au_fset_opts(opts->flags, REFRESH_DIR);
1298 au_fset_opts(opts->flags, REFRESH_NONDIR);
1307 static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
1308 struct au_opt_xino **opt_xino,
1309 struct au_opts *opts)
1312 aufs_bindex_t bend, bindex;
1313 struct dentry *root, *parent, *h_root;
1316 switch (opt->type) {
1318 err = au_xino_set(sb, &opt->xino,
1319 !!au_ftest_opts(opts->flags, REMOUNT));
1323 *opt_xino = &opt->xino;
1324 au_xino_brid_set(sb, -1);
1326 /* safe d_parent access */
1327 parent = opt->xino.file->f_dentry->d_parent;
1329 bend = au_sbend(sb);
1330 for (bindex = 0; bindex <= bend; bindex++) {
1331 h_root = au_h_dptr(root, bindex);
1332 if (h_root == parent) {
1333 au_xino_brid_set(sb, au_sbr_id(sb, bindex));
1341 au_xino_brid_set(sb, -1);
1342 *opt_xino = (void *)-1;
1349 int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
1350 unsigned int pending)
1353 aufs_bindex_t bindex, bend;
1354 unsigned char do_plink, skip, do_free;
1355 struct au_branch *br;
1357 struct dentry *root;
1358 struct inode *dir, *h_dir;
1359 struct au_sbinfo *sbinfo;
1360 struct au_hinode *hdir;
1364 sbinfo = au_sbi(sb);
1365 AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
1367 if (!(sb_flags & MS_RDONLY)) {
1368 if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
1369 pr_warning("first branch should be rw\n");
1370 if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
1371 pr_warning("shwh should be used with ro\n");
1374 if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1375 && !au_opt_test(sbinfo->si_mntflags, XINO))
1376 pr_warning("udba=*notify requires xino\n");
1380 dir = root->d_inode;
1381 do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
1382 bend = au_sbend(sb);
1383 for (bindex = 0; !err && bindex <= bend; bindex++) {
1385 h_dir = au_h_iptr(dir, bindex);
1386 br = au_sbr(sb, bindex);
1391 wbr_wh_read_lock(wbr);
1393 switch (br->br_perm) {
1400 || (!wbr->wbr_whbase
1402 && !wbr->wbr_orph));
1405 case AuBrPerm_RWNoLinkWH:
1406 /* skip = (!br->br_whbase && !br->br_orph); */
1407 skip = (!wbr || !wbr->wbr_whbase);
1410 skip = !!wbr->wbr_plink;
1412 skip = !wbr->wbr_plink;
1417 /* skip = (br->br_whbase && br->br_ohph); */
1418 skip = (wbr && wbr->wbr_whbase);
1421 skip = !!wbr->wbr_plink;
1423 skip = !wbr->wbr_plink;
1431 wbr_wh_read_unlock(wbr);
1436 hdir = au_hi(dir, bindex);
1437 au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1439 wbr_wh_write_lock(wbr);
1440 err = au_wh_init(au_h_dptr(root, bindex), br, sb);
1442 wbr_wh_write_unlock(wbr);
1443 au_hn_imtx_unlock(hdir);
1445 if (!err && do_free) {
1454 int au_opts_mount(struct super_block *sb, struct au_opts *opts)
1460 struct au_opt_xino *opt_xino, xino;
1461 struct au_sbinfo *sbinfo;
1463 SiMustWriteLock(sb);
1468 while (err >= 0 && opt->type != Opt_tail)
1469 err = au_opt_simple(sb, opt++, opts);
1472 else if (unlikely(err < 0))
1475 /* disable xino and udba temporary */
1476 sbinfo = au_sbi(sb);
1477 tmp = sbinfo->si_mntflags;
1478 au_opt_clr(sbinfo->si_mntflags, XINO);
1479 au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
1482 while (err >= 0 && opt->type != Opt_tail)
1483 err = au_opt_br(sb, opt++, opts);
1486 else if (unlikely(err < 0))
1489 bend = au_sbend(sb);
1490 if (unlikely(bend < 0)) {
1492 pr_err("no branches\n");
1496 if (au_opt_test(tmp, XINO))
1497 au_opt_set(sbinfo->si_mntflags, XINO);
1499 while (!err && opt->type != Opt_tail)
1500 err = au_opt_xino(sb, opt++, &opt_xino, opts);
1504 err = au_opts_verify(sb, sb->s_flags, tmp);
1509 if (au_opt_test(tmp, XINO) && !opt_xino) {
1510 xino.file = au_xino_def(sb);
1511 err = PTR_ERR(xino.file);
1512 if (IS_ERR(xino.file))
1515 err = au_xino_set(sb, &xino, /*remount*/0);
1522 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1523 sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
1524 if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1525 struct inode *dir = sb->s_root->d_inode;
1526 au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1533 int au_opts_remount(struct super_block *sb, struct au_opts *opts)
1537 struct au_opt_xino *opt_xino;
1539 struct au_sbinfo *sbinfo;
1541 SiMustWriteLock(sb);
1543 dir = sb->s_root->d_inode;
1544 sbinfo = au_sbi(sb);
1548 while (err >= 0 && opt->type != Opt_tail) {
1549 err = au_opt_simple(sb, opt, opts);
1551 err = au_opt_br(sb, opt, opts);
1553 err = au_opt_xino(sb, opt, &opt_xino, opts);
1559 /* go on even err */
1561 rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
1562 if (unlikely(rerr && !err))
1565 if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
1566 rerr = au_xib_trunc(sb);
1567 if (unlikely(rerr && !err))
1571 /* will be handled by the caller */
1572 if (!au_ftest_opts(opts->flags, REFRESH_DIR)
1573 && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
1574 au_fset_opts(opts->flags, REFRESH_DIR);
1576 AuDbg("status 0x%x\n", opts->flags);
1580 /* ---------------------------------------------------------------------- */
1582 unsigned int au_opt_udba(struct super_block *sb)
1584 return au_mntflags(sb) & AuOptMask_UDBA;