2 * Copyright (C) 2005-2013 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/namei.h>
24 #include <linux/types.h> /* a distribution requires */
25 #include <linux/parser.h>
28 /* ---------------------------------------------------------------------- */
32 Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
33 Opt_idel, Opt_imod, Opt_ireorder,
34 Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
35 Opt_rdblk_def, Opt_rdhash_def,
36 Opt_xino, Opt_zxino, Opt_noxino,
37 Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
38 Opt_trunc_xino_path, Opt_itrunc_xino,
39 Opt_trunc_xib, Opt_notrunc_xib,
41 Opt_plink, Opt_noplink, Opt_list_plink,
44 /* Opt_lock, Opt_unlock, */
45 Opt_cmd, Opt_cmd_args,
46 Opt_diropq_a, Opt_diropq_w,
47 Opt_warn_perm, Opt_nowarn_perm,
48 Opt_wbr_copyup, Opt_wbr_create,
49 Opt_refrof, Opt_norefrof,
50 Opt_verbose, Opt_noverbose,
51 Opt_sum, Opt_nosum, Opt_wsum,
52 Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
55 static match_table_t options = {
59 {Opt_add, "add=%d:%s"},
60 {Opt_add, "add:%d:%s"},
61 {Opt_add, "ins=%d:%s"},
62 {Opt_add, "ins:%d:%s"},
63 {Opt_append, "append=%s"},
64 {Opt_append, "append:%s"},
65 {Opt_prepend, "prepend=%s"},
66 {Opt_prepend, "prepend:%s"},
70 /* {Opt_idel, "idel:%d"}, */
73 /* {Opt_imod, "imod:%d:%s"}, */
75 {Opt_dirwh, "dirwh=%d"},
77 {Opt_xino, "xino=%s"},
78 {Opt_noxino, "noxino"},
79 {Opt_trunc_xino, "trunc_xino"},
80 {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
81 {Opt_notrunc_xino, "notrunc_xino"},
82 {Opt_trunc_xino_path, "trunc_xino=%s"},
83 {Opt_itrunc_xino, "itrunc_xino=%d"},
84 /* {Opt_zxino, "zxino=%s"}, */
85 {Opt_trunc_xib, "trunc_xib"},
86 {Opt_notrunc_xib, "notrunc_xib"},
91 {Opt_ignore_silent, "plink"},
94 {Opt_noplink, "noplink"},
96 #ifdef CONFIG_AUFS_DEBUG
97 {Opt_list_plink, "list_plink"},
100 {Opt_udba, "udba=%s"},
103 {Opt_nodio, "nodio"},
105 {Opt_diropq_a, "diropq=always"},
106 {Opt_diropq_a, "diropq=a"},
107 {Opt_diropq_w, "diropq=whiteouted"},
108 {Opt_diropq_w, "diropq=w"},
110 {Opt_warn_perm, "warn_perm"},
111 {Opt_nowarn_perm, "nowarn_perm"},
113 /* keep them temporary */
114 {Opt_ignore_silent, "coo=%s"},
115 {Opt_ignore_silent, "nodlgt"},
116 {Opt_ignore_silent, "nodirperm1"},
117 {Opt_ignore_silent, "clean_plink"},
119 #ifdef CONFIG_AUFS_SHWH
122 {Opt_noshwh, "noshwh"},
124 {Opt_rendir, "rendir=%d"},
126 {Opt_refrof, "refrof"},
127 {Opt_norefrof, "norefrof"},
129 {Opt_verbose, "verbose"},
131 {Opt_noverbose, "noverbose"},
132 {Opt_noverbose, "quiet"},
133 {Opt_noverbose, "q"},
134 {Opt_noverbose, "silent"},
137 {Opt_nosum, "nosum"},
140 {Opt_rdcache, "rdcache=%d"},
141 {Opt_rdblk, "rdblk=%d"},
142 {Opt_rdblk_def, "rdblk=def"},
143 {Opt_rdhash, "rdhash=%d"},
144 {Opt_rdhash_def, "rdhash=def"},
146 {Opt_wbr_create, "create=%s"},
147 {Opt_wbr_create, "create_policy=%s"},
148 {Opt_wbr_copyup, "cpup=%s"},
149 {Opt_wbr_copyup, "copyup=%s"},
150 {Opt_wbr_copyup, "copyup_policy=%s"},
152 /* internal use for the scripts */
153 {Opt_ignore_silent, "si=%s"},
156 {Opt_ignore, "debug=%d"},
157 {Opt_ignore, "delete=whiteout"},
158 {Opt_ignore, "delete=all"},
159 {Opt_ignore, "imap=%s"},
161 /* temporary workaround, due to old mount(8)? */
162 {Opt_ignore_silent, "relatime"},
167 /* ---------------------------------------------------------------------- */
169 static const char *au_parser_pattern(int val, struct match_token *token)
171 while (token->pattern) {
172 if (token->token == val)
173 return token->pattern;
180 /* ---------------------------------------------------------------------- */
182 static match_table_t brperm = {
183 {AuBrPerm_RO, AUFS_BRPERM_RO},
184 {AuBrPerm_RR, AUFS_BRPERM_RR},
185 {AuBrPerm_RW, AUFS_BRPERM_RW},
189 static match_table_t brattr = {
190 {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
191 {AuBrRAttr_WH, AUFS_BRRATTR_WH},
192 {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
196 #define AuBrStr_LONGEST AUFS_BRPERM_RW \
197 "+" AUFS_BRATTR_UNPIN \
198 "+" AUFS_BRWATTR_NLWH
200 static int br_attr_val(char *str, match_table_t table, substring_t args[])
207 p = strchr(str, '+');
210 v = match_token(str, table, args);
216 pr_warn("ignored branch attribute %s\n", str);
226 static int noinline_for_stack br_perm_val(char *perm)
230 substring_t args[MAX_OPT_ARGS];
232 p = strchr(perm, '+');
235 val = match_token(perm, brperm, args);
239 pr_warn("ignored branch permission %s\n", perm);
251 val |= br_attr_val(p, brattr, args);
258 switch (val & AuBrPerm_Mask) {
261 if (unlikely(val & AuBrWAttr_NoLinkWH)) {
262 pr_warn("ignored branch attribute %s\n",
264 val &= ~AuBrWAttr_NoLinkWH;
268 if (unlikely(val & AuBrRAttr_WH)) {
269 pr_warn("ignored branch attribute %s\n",
271 val &= ~AuBrRAttr_WH;
280 /* Caller should free the return value */
281 char *au_optstr_br_perm(int brperm)
283 char *p, a[sizeof(AuBrStr_LONGEST)];
286 #define SetPerm(str) do { \
288 memcpy(a, str, sz); \
292 #define AppendAttr(flag, str) do { \
293 if (brperm & flag) { \
296 memcpy(p, str, sz); \
301 switch (brperm & AuBrPerm_Mask) {
303 SetPerm(AUFS_BRPERM_RO);
306 SetPerm(AUFS_BRPERM_RR);
309 SetPerm(AUFS_BRPERM_RW);
315 AppendAttr(AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN);
316 AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
317 AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
319 AuDebugOn(strlen(a) >= sizeof(a));
320 return kstrdup(a, GFP_NOFS);
325 /* ---------------------------------------------------------------------- */
327 static match_table_t udbalevel = {
328 {AuOpt_UDBA_REVAL, "reval"},
329 {AuOpt_UDBA_NONE, "none"},
330 #ifdef CONFIG_AUFS_HNOTIFY
331 {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
332 #ifdef CONFIG_AUFS_HFSNOTIFY
333 {AuOpt_UDBA_HNOTIFY, "fsnotify"},
339 static int noinline_for_stack udba_val(char *str)
341 substring_t args[MAX_OPT_ARGS];
343 return match_token(str, udbalevel, args);
346 const char *au_optstr_udba(int udba)
348 return au_parser_pattern(udba, (void *)udbalevel);
351 /* ---------------------------------------------------------------------- */
353 static match_table_t au_wbr_create_policy = {
354 {AuWbrCreate_TDP, "tdp"},
355 {AuWbrCreate_TDP, "top-down-parent"},
356 {AuWbrCreate_RR, "rr"},
357 {AuWbrCreate_RR, "round-robin"},
358 {AuWbrCreate_MFS, "mfs"},
359 {AuWbrCreate_MFS, "most-free-space"},
360 {AuWbrCreate_MFSV, "mfs:%d"},
361 {AuWbrCreate_MFSV, "most-free-space:%d"},
363 {AuWbrCreate_MFSRR, "mfsrr:%d"},
364 {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
365 {AuWbrCreate_PMFS, "pmfs"},
366 {AuWbrCreate_PMFSV, "pmfs:%d"},
367 {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
368 {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
374 * cf. linux/lib/parser.c and cmdline.c
375 * gave up calling memparse() since it uses simple_strtoull() instead of
378 static int noinline_for_stack
379 au_match_ull(substring_t *s, unsigned long long *result)
386 len = s->to - s->from;
387 if (len + 1 <= sizeof(a)) {
388 memcpy(a, s->from, len);
390 err = kstrtoull(a, 0, result);
395 static int au_wbr_mfs_wmark(substring_t *arg, char *str,
396 struct au_opt_wbr_create *create)
399 unsigned long long ull;
402 if (!au_match_ull(arg, &ull))
403 create->mfsrr_watermark = ull;
405 pr_err("bad integer in %s\n", str);
412 static int au_wbr_mfs_sec(substring_t *arg, char *str,
413 struct au_opt_wbr_create *create)
418 if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
419 create->mfs_second = n;
421 pr_err("bad integer in %s\n", str);
428 static int noinline_for_stack
429 au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
432 substring_t args[MAX_OPT_ARGS];
434 err = match_token(str, au_wbr_create_policy, args);
435 create->wbr_create = err;
437 case AuWbrCreate_MFSRRV:
438 case AuWbrCreate_PMFSRRV:
439 e = au_wbr_mfs_wmark(&args[0], str, create);
441 e = au_wbr_mfs_sec(&args[1], str, create);
445 case AuWbrCreate_MFSRR:
446 case AuWbrCreate_PMFSRR:
447 e = au_wbr_mfs_wmark(&args[0], str, create);
453 case AuWbrCreate_MFS:
454 case AuWbrCreate_PMFS:
455 create->mfs_second = AUFS_MFS_DEF_SEC;
457 case AuWbrCreate_MFSV:
458 case AuWbrCreate_PMFSV:
459 e = au_wbr_mfs_sec(&args[0], str, create);
468 const char *au_optstr_wbr_create(int wbr_create)
470 return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
473 static match_table_t au_wbr_copyup_policy = {
474 {AuWbrCopyup_TDP, "tdp"},
475 {AuWbrCopyup_TDP, "top-down-parent"},
476 {AuWbrCopyup_BUP, "bup"},
477 {AuWbrCopyup_BUP, "bottom-up-parent"},
478 {AuWbrCopyup_BU, "bu"},
479 {AuWbrCopyup_BU, "bottom-up"},
483 static int noinline_for_stack au_wbr_copyup_val(char *str)
485 substring_t args[MAX_OPT_ARGS];
487 return match_token(str, au_wbr_copyup_policy, args);
490 const char *au_optstr_wbr_copyup(int wbr_copyup)
492 return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
495 /* ---------------------------------------------------------------------- */
497 static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
499 static void dump_opts(struct au_opts *opts)
501 #ifdef CONFIG_AUFS_DEBUG
502 /* reduce stack space */
504 struct au_opt_add *add;
505 struct au_opt_del *del;
506 struct au_opt_mod *mod;
507 struct au_opt_xino *xino;
508 struct au_opt_xino_itrunc *xino_itrunc;
509 struct au_opt_wbr_create *create;
514 while (opt->type != Opt_tail) {
518 AuDbg("add {b%d, %s, 0x%x, %p}\n",
519 u.add->bindex, u.add->pathname, u.add->perm,
525 AuDbg("del {%s, %p}\n",
526 u.del->pathname, u.del->h_path.dentry);
531 AuDbg("mod {%s, 0x%x, %p}\n",
532 u.mod->path, u.mod->perm, u.mod->h_root);
536 AuDbg("append {b%d, %s, 0x%x, %p}\n",
537 u.add->bindex, u.add->pathname, u.add->perm,
542 AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
543 u.add->bindex, u.add->pathname, u.add->perm,
547 AuDbg("dirwh %d\n", opt->dirwh);
550 AuDbg("rdcache %d\n", opt->rdcache);
553 AuDbg("rdblk %u\n", opt->rdblk);
556 AuDbg("rdblk_def\n");
559 AuDbg("rdhash %u\n", opt->rdhash);
562 AuDbg("rdhash_def\n");
566 AuDbg("xino {%s %.*s}\n",
568 AuDLNPair(u.xino->file->f_dentry));
573 case Opt_notrunc_xino:
574 AuLabel(notrunc_xino);
576 case Opt_trunc_xino_path:
577 case Opt_itrunc_xino:
578 u.xino_itrunc = &opt->xino_itrunc;
579 AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
588 case Opt_notrunc_xib:
589 AuLabel(notrunc_xib);
607 AuDbg("udba %d, %s\n",
608 opt->udba, au_optstr_udba(opt->udba));
625 case Opt_nowarn_perm:
626 AuLabel(nowarn_perm);
650 u.create = &opt->wbr_create;
651 AuDbg("create %d, %s\n", u.create->wbr_create,
652 au_optstr_wbr_create(u.create->wbr_create));
653 switch (u.create->wbr_create) {
654 case AuWbrCreate_MFSV:
655 case AuWbrCreate_PMFSV:
656 AuDbg("%d sec\n", u.create->mfs_second);
658 case AuWbrCreate_MFSRR:
659 AuDbg("%llu watermark\n",
660 u.create->mfsrr_watermark);
662 case AuWbrCreate_MFSRRV:
663 case AuWbrCreate_PMFSRRV:
664 AuDbg("%llu watermark, %d sec\n",
665 u.create->mfsrr_watermark,
666 u.create->mfs_second);
671 AuDbg("copyup %d, %s\n", opt->wbr_copyup,
672 au_optstr_wbr_copyup(opt->wbr_copyup));
682 void au_opts_free(struct au_opts *opts)
687 while (opt->type != Opt_tail) {
692 path_put(&opt->add.path);
696 path_put(&opt->del.h_path);
700 dput(opt->mod.h_root);
703 fput(opt->xino.file);
710 static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
711 aufs_bindex_t bindex)
714 struct au_opt_add *add = &opt->add;
717 add->bindex = bindex;
718 add->perm = AuBrPerm_RO;
719 add->pathname = opt_str;
720 p = strchr(opt_str, '=');
724 add->perm = br_perm_val(p);
727 err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
730 add->perm = AuBrPerm_RO;
731 if (au_test_fs_rr(add->path.dentry->d_sb))
732 add->perm = AuBrPerm_RR;
733 else if (!bindex && !(sb_flags & MS_RDONLY))
734 add->perm = AuBrPerm_RW;
739 pr_err("lookup failed %s (%d)\n", add->pathname, err);
746 static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
750 del->pathname = args[0].from;
751 AuDbg("del path %s\n", del->pathname);
753 err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
755 pr_err("lookup failed %s (%d)\n", del->pathname, err);
760 #if 0 /* reserved for future use */
761 static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
762 struct au_opt_del *del, substring_t args[])
769 aufs_read_lock(root, AuLock_FLUSH);
770 if (bindex < 0 || au_sbend(sb) < bindex) {
771 pr_err("out of bounds, %d\n", bindex);
776 del->h_path.dentry = dget(au_h_dptr(root, bindex));
777 del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
780 aufs_read_unlock(root, !AuLock_IR);
785 static int noinline_for_stack
786 au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
793 mod->path = args[0].from;
794 p = strchr(mod->path, '=');
796 pr_err("no permssion %s\n", args[0].from);
801 err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
803 pr_err("lookup failed %s (%d)\n", mod->path, err);
807 mod->perm = br_perm_val(p);
808 AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
809 mod->h_root = dget(path.dentry);
816 #if 0 /* reserved for future use */
817 static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
818 struct au_opt_mod *mod, substring_t args[])
825 aufs_read_lock(root, AuLock_FLUSH);
826 if (bindex < 0 || au_sbend(sb) < bindex) {
827 pr_err("out of bounds, %d\n", bindex);
832 mod->perm = br_perm_val(args[1].from);
833 AuDbg("mod path %s, perm 0x%x, %s\n",
834 mod->path, mod->perm, args[1].from);
835 mod->h_root = dget(au_h_dptr(root, bindex));
838 aufs_read_unlock(root, !AuLock_IR);
843 static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
849 file = au_xino_create(sb, args[0].from, /*silent*/0);
855 if (unlikely(file->f_dentry->d_sb == sb)) {
857 pr_err("%s must be outside\n", args[0].from);
863 xino->path = args[0].from;
869 static int noinline_for_stack
870 au_opts_parse_xino_itrunc_path(struct super_block *sb,
871 struct au_opt_xino_itrunc *xino_itrunc,
875 aufs_bindex_t bend, bindex;
879 err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
881 pr_err("lookup failed %s (%d)\n", args[0].from, err);
885 xino_itrunc->bindex = -1;
887 aufs_read_lock(root, AuLock_FLUSH);
889 for (bindex = 0; bindex <= bend; bindex++) {
890 if (au_h_dptr(root, bindex) == path.dentry) {
891 xino_itrunc->bindex = bindex;
895 aufs_read_unlock(root, !AuLock_IR);
898 if (unlikely(xino_itrunc->bindex < 0)) {
899 pr_err("no such branch %s\n", args[0].from);
907 /* called without aufs lock */
908 int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
911 aufs_bindex_t bindex;
912 unsigned char skipped;
914 struct au_opt *opt, *opt_tail;
916 /* reduce the stack space */
918 struct au_opt_xino_itrunc *xino_itrunc;
919 struct au_opt_wbr_create *create;
922 substring_t args[MAX_OPT_ARGS];
926 a = kmalloc(sizeof(*a), GFP_NOFS);
934 opt_tail = opt + opts->max_opt - 1;
935 opt->type = Opt_tail;
936 while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
939 token = match_token(opt_str, options, a->args);
943 while (!err && (opt_str = strsep(&a->args[0].from, ":"))
945 err = opt_add(opt, opt_str, opts->sb_flags,
947 if (unlikely(!err && ++opt > opt_tail)) {
951 opt->type = Opt_tail;
956 if (unlikely(match_int(&a->args[0], &n))) {
957 pr_err("bad integer in %s\n", opt_str);
961 err = opt_add(opt, a->args[1].from, opts->sb_flags,
967 err = opt_add(opt, a->args[0].from, opts->sb_flags,
973 err = opt_add(opt, a->args[0].from, opts->sb_flags,
979 err = au_opts_parse_del(&opt->del, a->args);
983 #if 0 /* reserved for future use */
985 del->pathname = "(indexed)";
986 if (unlikely(match_int(&args[0], &n))) {
987 pr_err("bad integer in %s\n", opt_str);
990 err = au_opts_parse_idel(sb, n, &opt->del, a->args);
996 err = au_opts_parse_mod(&opt->mod, a->args);
1000 #ifdef IMOD /* reserved for future use */
1002 u.mod->path = "(indexed)";
1003 if (unlikely(match_int(&a->args[0], &n))) {
1004 pr_err("bad integer in %s\n", opt_str);
1007 err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
1013 err = au_opts_parse_xino(sb, &opt->xino, a->args);
1018 case Opt_trunc_xino_path:
1019 err = au_opts_parse_xino_itrunc_path
1020 (sb, &opt->xino_itrunc, a->args);
1025 case Opt_itrunc_xino:
1026 u.xino_itrunc = &opt->xino_itrunc;
1027 if (unlikely(match_int(&a->args[0], &n))) {
1028 pr_err("bad integer in %s\n", opt_str);
1031 u.xino_itrunc->bindex = n;
1032 aufs_read_lock(root, AuLock_FLUSH);
1033 if (n < 0 || au_sbend(sb) < n) {
1034 pr_err("out of bounds, %d\n", n);
1035 aufs_read_unlock(root, !AuLock_IR);
1038 aufs_read_unlock(root, !AuLock_IR);
1044 if (unlikely(match_int(&a->args[0], &opt->dirwh)))
1051 if (unlikely(match_int(&a->args[0], &n))) {
1052 pr_err("bad integer in %s\n", opt_str);
1055 if (unlikely(n > AUFS_RDCACHE_MAX)) {
1056 pr_err("rdcache must be smaller than %d\n",
1065 if (unlikely(match_int(&a->args[0], &n)
1067 || n > KMALLOC_MAX_SIZE)) {
1068 pr_err("bad integer in %s\n", opt_str);
1071 if (unlikely(n && n < NAME_MAX)) {
1072 pr_err("rdblk must be larger than %d\n",
1081 if (unlikely(match_int(&a->args[0], &n)
1083 || n * sizeof(struct hlist_head)
1084 > KMALLOC_MAX_SIZE)) {
1085 pr_err("bad integer in %s\n", opt_str);
1093 case Opt_trunc_xino:
1094 case Opt_notrunc_xino:
1097 case Opt_notrunc_xib:
1102 case Opt_list_plink:
1108 case Opt_nowarn_perm:
1117 case Opt_rdhash_def:
1123 opt->udba = udba_val(a->args[0].from);
1124 if (opt->udba >= 0) {
1128 pr_err("wrong value, %s\n", opt_str);
1131 case Opt_wbr_create:
1132 u.create = &opt->wbr_create;
1133 u.create->wbr_create
1134 = au_wbr_create_val(a->args[0].from, u.create);
1135 if (u.create->wbr_create >= 0) {
1139 pr_err("wrong value, %s\n", opt_str);
1141 case Opt_wbr_copyup:
1142 opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
1143 if (opt->wbr_copyup >= 0) {
1147 pr_err("wrong value, %s\n", opt_str);
1151 pr_warn("ignored %s\n", opt_str);
1153 case Opt_ignore_silent:
1158 pr_err("unknown option %s\n", opt_str);
1162 if (!err && !skipped) {
1163 if (unlikely(++opt > opt_tail)) {
1166 opt->type = Opt_tail;
1169 opt->type = Opt_tail;
1182 static int au_opt_wbr_create(struct super_block *sb,
1183 struct au_opt_wbr_create *create)
1186 struct au_sbinfo *sbinfo;
1188 SiMustWriteLock(sb);
1190 err = 1; /* handled */
1191 sbinfo = au_sbi(sb);
1192 if (sbinfo->si_wbr_create_ops->fin) {
1193 err = sbinfo->si_wbr_create_ops->fin(sb);
1198 sbinfo->si_wbr_create = create->wbr_create;
1199 sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
1200 switch (create->wbr_create) {
1201 case AuWbrCreate_MFSRRV:
1202 case AuWbrCreate_MFSRR:
1203 case AuWbrCreate_PMFSRR:
1204 case AuWbrCreate_PMFSRRV:
1205 sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
1207 case AuWbrCreate_MFS:
1208 case AuWbrCreate_MFSV:
1209 case AuWbrCreate_PMFS:
1210 case AuWbrCreate_PMFSV:
1211 sbinfo->si_wbr_mfs.mfs_expire
1212 = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1216 if (sbinfo->si_wbr_create_ops->init)
1217 sbinfo->si_wbr_create_ops->init(sb); /* ignore */
1224 * plus: processed without an error
1227 static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
1228 struct au_opts *opts)
1231 struct au_sbinfo *sbinfo;
1233 SiMustWriteLock(sb);
1235 err = 1; /* handled */
1236 sbinfo = au_sbi(sb);
1237 switch (opt->type) {
1239 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1240 sbinfo->si_mntflags |= opt->udba;
1241 opts->given_udba |= opt->udba;
1245 au_opt_set(sbinfo->si_mntflags, PLINK);
1248 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1249 au_plink_put(sb, /*verbose*/1);
1250 au_opt_clr(sbinfo->si_mntflags, PLINK);
1252 case Opt_list_plink:
1253 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1258 au_opt_set(sbinfo->si_mntflags, DIO);
1259 au_fset_opts(opts->flags, REFRESH_DYAOP);
1262 au_opt_clr(sbinfo->si_mntflags, DIO);
1263 au_fset_opts(opts->flags, REFRESH_DYAOP);
1267 au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1270 au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1274 au_opt_set(sbinfo->si_mntflags, WARN_PERM);
1276 case Opt_nowarn_perm:
1277 au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
1281 au_opt_set(sbinfo->si_mntflags, REFROF);
1284 au_opt_clr(sbinfo->si_mntflags, REFROF);
1288 au_opt_set(sbinfo->si_mntflags, VERBOSE);
1291 au_opt_clr(sbinfo->si_mntflags, VERBOSE);
1295 au_opt_set(sbinfo->si_mntflags, SUM);
1298 au_opt_clr(sbinfo->si_mntflags, SUM);
1299 au_opt_set(sbinfo->si_mntflags, SUM_W);
1301 au_opt_clr(sbinfo->si_mntflags, SUM);
1302 au_opt_clr(sbinfo->si_mntflags, SUM_W);
1305 case Opt_wbr_create:
1306 err = au_opt_wbr_create(sb, &opt->wbr_create);
1308 case Opt_wbr_copyup:
1309 sbinfo->si_wbr_copyup = opt->wbr_copyup;
1310 sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
1314 sbinfo->si_dirwh = opt->dirwh;
1319 = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1322 sbinfo->si_rdblk = opt->rdblk;
1325 sbinfo->si_rdblk = AUFS_RDBLK_DEF;
1328 sbinfo->si_rdhash = opt->rdhash;
1330 case Opt_rdhash_def:
1331 sbinfo->si_rdhash = AUFS_RDHASH_DEF;
1335 au_opt_set(sbinfo->si_mntflags, SHWH);
1338 au_opt_clr(sbinfo->si_mntflags, SHWH);
1341 case Opt_trunc_xino:
1342 au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
1344 case Opt_notrunc_xino:
1345 au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
1348 case Opt_trunc_xino_path:
1349 case Opt_itrunc_xino:
1350 err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
1356 au_fset_opts(opts->flags, TRUNC_XIB);
1358 case Opt_notrunc_xib:
1359 au_fclr_opts(opts->flags, TRUNC_XIB);
1371 * returns tri-state.
1372 * plus: processed without an error
1376 static int au_opt_br(struct super_block *sb, struct au_opt *opt,
1377 struct au_opts *opts)
1379 int err, do_refresh;
1382 switch (opt->type) {
1384 opt->add.bindex = au_sbend(sb) + 1;
1385 if (opt->add.bindex < 0)
1386 opt->add.bindex = 0;
1389 opt->add.bindex = 0;
1392 err = au_br_add(sb, &opt->add,
1393 au_ftest_opts(opts->flags, REMOUNT));
1396 au_fset_opts(opts->flags, REFRESH);
1402 err = au_br_del(sb, &opt->del,
1403 au_ftest_opts(opts->flags, REMOUNT));
1406 au_fset_opts(opts->flags, TRUNC_XIB);
1407 au_fset_opts(opts->flags, REFRESH);
1413 err = au_br_mod(sb, &opt->mod,
1414 au_ftest_opts(opts->flags, REMOUNT),
1419 au_fset_opts(opts->flags, REFRESH);
1427 static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
1428 struct au_opt_xino **opt_xino,
1429 struct au_opts *opts)
1432 aufs_bindex_t bend, bindex;
1433 struct dentry *root, *parent, *h_root;
1436 switch (opt->type) {
1438 err = au_xino_set(sb, &opt->xino,
1439 !!au_ftest_opts(opts->flags, REMOUNT));
1443 *opt_xino = &opt->xino;
1444 au_xino_brid_set(sb, -1);
1446 /* safe d_parent access */
1447 parent = opt->xino.file->f_dentry->d_parent;
1449 bend = au_sbend(sb);
1450 for (bindex = 0; bindex <= bend; bindex++) {
1451 h_root = au_h_dptr(root, bindex);
1452 if (h_root == parent) {
1453 au_xino_brid_set(sb, au_sbr_id(sb, bindex));
1461 au_xino_brid_set(sb, -1);
1462 *opt_xino = (void *)-1;
1469 int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
1470 unsigned int pending)
1473 aufs_bindex_t bindex, bend;
1474 unsigned char do_plink, skip, do_free;
1475 struct au_branch *br;
1477 struct dentry *root;
1478 struct inode *dir, *h_dir;
1479 struct au_sbinfo *sbinfo;
1480 struct au_hinode *hdir;
1484 sbinfo = au_sbi(sb);
1485 AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
1487 if (!(sb_flags & MS_RDONLY)) {
1488 if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
1489 pr_warn("first branch should be rw\n");
1490 if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
1491 pr_warn("shwh should be used with ro\n");
1494 if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1495 && !au_opt_test(sbinfo->si_mntflags, XINO))
1496 pr_warn("udba=*notify requires xino\n");
1500 dir = root->d_inode;
1501 do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
1502 bend = au_sbend(sb);
1503 for (bindex = 0; !err && bindex <= bend; bindex++) {
1505 h_dir = au_h_iptr(dir, bindex);
1506 br = au_sbr(sb, bindex);
1511 wbr_wh_read_lock(wbr);
1513 if (!au_br_writable(br->br_perm)) {
1516 || (!wbr->wbr_whbase
1518 && !wbr->wbr_orph));
1519 } else if (!au_br_wh_linkable(br->br_perm)) {
1520 /* skip = (!br->br_whbase && !br->br_orph); */
1521 skip = (!wbr || !wbr->wbr_whbase);
1524 skip = !!wbr->wbr_plink;
1526 skip = !wbr->wbr_plink;
1529 /* skip = (br->br_whbase && br->br_ohph); */
1530 skip = (wbr && wbr->wbr_whbase);
1533 skip = !!wbr->wbr_plink;
1535 skip = !wbr->wbr_plink;
1539 wbr_wh_read_unlock(wbr);
1544 hdir = au_hi(dir, bindex);
1545 au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1547 wbr_wh_write_lock(wbr);
1548 err = au_wh_init(br, sb);
1550 wbr_wh_write_unlock(wbr);
1551 au_hn_imtx_unlock(hdir);
1553 if (!err && do_free) {
1562 int au_opts_mount(struct super_block *sb, struct au_opts *opts)
1566 aufs_bindex_t bindex, bend;
1568 struct au_opt_xino *opt_xino, xino;
1569 struct au_sbinfo *sbinfo;
1570 struct au_branch *br;
1572 SiMustWriteLock(sb);
1577 while (err >= 0 && opt->type != Opt_tail)
1578 err = au_opt_simple(sb, opt++, opts);
1581 else if (unlikely(err < 0))
1584 /* disable xino and udba temporary */
1585 sbinfo = au_sbi(sb);
1586 tmp = sbinfo->si_mntflags;
1587 au_opt_clr(sbinfo->si_mntflags, XINO);
1588 au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
1591 while (err >= 0 && opt->type != Opt_tail)
1592 err = au_opt_br(sb, opt++, opts);
1595 else if (unlikely(err < 0))
1598 bend = au_sbend(sb);
1599 if (unlikely(bend < 0)) {
1601 pr_err("no branches\n");
1605 if (au_opt_test(tmp, XINO))
1606 au_opt_set(sbinfo->si_mntflags, XINO);
1608 while (!err && opt->type != Opt_tail)
1609 err = au_opt_xino(sb, opt++, &opt_xino, opts);
1613 err = au_opts_verify(sb, sb->s_flags, tmp);
1618 if (au_opt_test(tmp, XINO) && !opt_xino) {
1619 xino.file = au_xino_def(sb);
1620 err = PTR_ERR(xino.file);
1621 if (IS_ERR(xino.file))
1624 err = au_xino_set(sb, &xino, /*remount*/0);
1631 tmp &= AuOptMask_UDBA;
1632 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1633 sbinfo->si_mntflags |= tmp;
1634 bend = au_sbend(sb);
1635 for (bindex = 0; bindex <= bend; bindex++) {
1636 br = au_sbr(sb, bindex);
1637 err = au_hnotify_reset_br(tmp, br, br->br_perm);
1639 AuIOErr("hnotify failed on br %d, %d, ignored\n",
1641 /* go on even if err */
1643 if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1644 struct inode *dir = sb->s_root->d_inode;
1645 au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1652 int au_opts_remount(struct super_block *sb, struct au_opts *opts)
1656 struct au_opt_xino *opt_xino;
1658 struct au_sbinfo *sbinfo;
1660 SiMustWriteLock(sb);
1662 dir = sb->s_root->d_inode;
1663 sbinfo = au_sbi(sb);
1667 while (err >= 0 && opt->type != Opt_tail) {
1668 err = au_opt_simple(sb, opt, opts);
1670 err = au_opt_br(sb, opt, opts);
1672 err = au_opt_xino(sb, opt, &opt_xino, opts);
1678 /* go on even err */
1680 rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
1681 if (unlikely(rerr && !err))
1684 if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
1685 rerr = au_xib_trunc(sb);
1686 if (unlikely(rerr && !err))
1690 /* will be handled by the caller */
1691 if (!au_ftest_opts(opts->flags, REFRESH)
1692 && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
1693 au_fset_opts(opts->flags, REFRESH);
1695 AuDbg("status 0x%x\n", opts->flags);
1699 /* ---------------------------------------------------------------------- */
1701 unsigned int au_opt_udba(struct super_block *sb)
1703 return au_mntflags(sb) & AuOptMask_UDBA;