]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - fs/aufs/opts.c
UBUNTU: SAUCE: aufs -- Convert to use xattr handlers
[mirror_ubuntu-zesty-kernel.git] / fs / aufs / opts.c
CommitLineData
5b88fdd9
SF
1/*
2 * Copyright (C) 2005-2016 Junjiro R. Okajima
3 *
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.
8 *
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.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * mount options/flags
20 */
21
22#include <linux/namei.h>
23#include <linux/types.h> /* a distribution requires */
24#include <linux/parser.h>
25#include "aufs.h"
26
27/* ---------------------------------------------------------------------- */
28
29enum {
30 Opt_br,
31 Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
32 Opt_idel, Opt_imod,
33 Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
34 Opt_rdblk_def, Opt_rdhash_def,
35 Opt_xino, Opt_noxino,
36 Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
37 Opt_trunc_xino_path, Opt_itrunc_xino,
38 Opt_trunc_xib, Opt_notrunc_xib,
39 Opt_shwh, Opt_noshwh,
40 Opt_plink, Opt_noplink, Opt_list_plink,
41 Opt_udba,
42 Opt_dio, Opt_nodio,
43 Opt_diropq_a, Opt_diropq_w,
44 Opt_warn_perm, Opt_nowarn_perm,
45 Opt_wbr_copyup, Opt_wbr_create,
46 Opt_fhsm_sec,
47 Opt_verbose, Opt_noverbose,
48 Opt_sum, Opt_nosum, Opt_wsum,
49 Opt_dirperm1, Opt_nodirperm1,
50 Opt_acl, Opt_noacl,
51 Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
52};
53
54static match_table_t options = {
55 {Opt_br, "br=%s"},
56 {Opt_br, "br:%s"},
57
58 {Opt_add, "add=%d:%s"},
59 {Opt_add, "add:%d:%s"},
60 {Opt_add, "ins=%d:%s"},
61 {Opt_add, "ins:%d:%s"},
62 {Opt_append, "append=%s"},
63 {Opt_append, "append:%s"},
64 {Opt_prepend, "prepend=%s"},
65 {Opt_prepend, "prepend:%s"},
66
67 {Opt_del, "del=%s"},
68 {Opt_del, "del:%s"},
69 /* {Opt_idel, "idel:%d"}, */
70 {Opt_mod, "mod=%s"},
71 {Opt_mod, "mod:%s"},
72 /* {Opt_imod, "imod:%d:%s"}, */
73
74 {Opt_dirwh, "dirwh=%d"},
75
76 {Opt_xino, "xino=%s"},
77 {Opt_noxino, "noxino"},
78 {Opt_trunc_xino, "trunc_xino"},
79 {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
80 {Opt_notrunc_xino, "notrunc_xino"},
81 {Opt_trunc_xino_path, "trunc_xino=%s"},
82 {Opt_itrunc_xino, "itrunc_xino=%d"},
83 /* {Opt_zxino, "zxino=%s"}, */
84 {Opt_trunc_xib, "trunc_xib"},
85 {Opt_notrunc_xib, "notrunc_xib"},
86
87#ifdef CONFIG_PROC_FS
88 {Opt_plink, "plink"},
89#else
90 {Opt_ignore_silent, "plink"},
91#endif
92
93 {Opt_noplink, "noplink"},
94
95#ifdef CONFIG_AUFS_DEBUG
96 {Opt_list_plink, "list_plink"},
97#endif
98
99 {Opt_udba, "udba=%s"},
100
101 {Opt_dio, "dio"},
102 {Opt_nodio, "nodio"},
103
104#ifdef CONFIG_AUFS_FHSM
105 {Opt_fhsm_sec, "fhsm_sec=%d"},
106#else
107 {Opt_ignore_silent, "fhsm_sec=%d"},
108#endif
109
110 {Opt_diropq_a, "diropq=always"},
111 {Opt_diropq_a, "diropq=a"},
112 {Opt_diropq_w, "diropq=whiteouted"},
113 {Opt_diropq_w, "diropq=w"},
114
115 {Opt_warn_perm, "warn_perm"},
116 {Opt_nowarn_perm, "nowarn_perm"},
117
118 /* keep them temporary */
119 {Opt_ignore_silent, "nodlgt"},
120 {Opt_ignore_silent, "clean_plink"},
121
122#ifdef CONFIG_AUFS_SHWH
123 {Opt_shwh, "shwh"},
124#endif
125 {Opt_noshwh, "noshwh"},
126
127 {Opt_dirperm1, "dirperm1"},
128 {Opt_nodirperm1, "nodirperm1"},
129
130 {Opt_verbose, "verbose"},
131 {Opt_verbose, "v"},
132 {Opt_noverbose, "noverbose"},
133 {Opt_noverbose, "quiet"},
134 {Opt_noverbose, "q"},
135 {Opt_noverbose, "silent"},
136
137 {Opt_sum, "sum"},
138 {Opt_nosum, "nosum"},
139 {Opt_wsum, "wsum"},
140
141 {Opt_rdcache, "rdcache=%d"},
142 {Opt_rdblk, "rdblk=%d"},
143 {Opt_rdblk_def, "rdblk=def"},
144 {Opt_rdhash, "rdhash=%d"},
145 {Opt_rdhash_def, "rdhash=def"},
146
147 {Opt_wbr_create, "create=%s"},
148 {Opt_wbr_create, "create_policy=%s"},
149 {Opt_wbr_copyup, "cpup=%s"},
150 {Opt_wbr_copyup, "copyup=%s"},
151 {Opt_wbr_copyup, "copyup_policy=%s"},
152
153 /* generic VFS flag */
154#ifdef CONFIG_FS_POSIX_ACL
155 {Opt_acl, "acl"},
156 {Opt_noacl, "noacl"},
157#else
158 {Opt_ignore_silent, "acl"},
159 {Opt_ignore_silent, "noacl"},
160#endif
161
162 /* internal use for the scripts */
163 {Opt_ignore_silent, "si=%s"},
164
165 {Opt_br, "dirs=%s"},
166 {Opt_ignore, "debug=%d"},
167 {Opt_ignore, "delete=whiteout"},
168 {Opt_ignore, "delete=all"},
169 {Opt_ignore, "imap=%s"},
170
171 /* temporary workaround, due to old mount(8)? */
172 {Opt_ignore_silent, "relatime"},
173
174 {Opt_err, NULL}
175};
176
177/* ---------------------------------------------------------------------- */
178
179static const char *au_parser_pattern(int val, match_table_t tbl)
180{
181 struct match_token *p;
182
183 p = tbl;
184 while (p->pattern) {
185 if (p->token == val)
186 return p->pattern;
187 p++;
188 }
189 BUG();
190 return "??";
191}
192
193static const char *au_optstr(int *val, match_table_t tbl)
194{
195 struct match_token *p;
196 int v;
197
198 v = *val;
199 if (!v)
200 goto out;
201 p = tbl;
202 while (p->pattern) {
203 if (p->token
204 && (v & p->token) == p->token) {
205 *val &= ~p->token;
206 return p->pattern;
207 }
208 p++;
209 }
210
211out:
212 return NULL;
213}
214
215/* ---------------------------------------------------------------------- */
216
217static match_table_t brperm = {
218 {AuBrPerm_RO, AUFS_BRPERM_RO},
219 {AuBrPerm_RR, AUFS_BRPERM_RR},
220 {AuBrPerm_RW, AUFS_BRPERM_RW},
221 {0, NULL}
222};
223
224static match_table_t brattr = {
225 /* general */
226 {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
227 {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
228 /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
229 {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
230#ifdef CONFIG_AUFS_FHSM
231 {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
232#endif
233#ifdef CONFIG_AUFS_XATTR
234 {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
235 {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
236 {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
237 {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
238 {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
239 {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
240#endif
241
242 /* ro/rr branch */
243 {AuBrRAttr_WH, AUFS_BRRATTR_WH},
244
245 /* rw branch */
246 {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
247 {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
248
249 {0, NULL}
250};
251
252static int br_attr_val(char *str, match_table_t table, substring_t args[])
253{
254 int attr, v;
255 char *p;
256
257 attr = 0;
258 do {
259 p = strchr(str, '+');
260 if (p)
261 *p = 0;
262 v = match_token(str, table, args);
263 if (v) {
264 if (v & AuBrAttr_CMOO_Mask)
265 attr &= ~AuBrAttr_CMOO_Mask;
266 attr |= v;
267 } else {
268 if (p)
269 *p = '+';
270 pr_warn("ignored branch attribute %s\n", str);
271 break;
272 }
273 if (p)
274 str = p + 1;
275 } while (p);
276
277 return attr;
278}
279
280static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
281{
282 int sz;
283 const char *p;
284 char *q;
285
286 q = str->a;
287 *q = 0;
288 p = au_optstr(&perm, brattr);
289 if (p) {
290 sz = strlen(p);
291 memcpy(q, p, sz + 1);
292 q += sz;
293 } else
294 goto out;
295
296 do {
297 p = au_optstr(&perm, brattr);
298 if (p) {
299 *q++ = '+';
300 sz = strlen(p);
301 memcpy(q, p, sz + 1);
302 q += sz;
303 }
304 } while (p);
305
306out:
307 return q - str->a;
308}
309
310static int noinline_for_stack br_perm_val(char *perm)
311{
312 int val, bad, sz;
313 char *p;
314 substring_t args[MAX_OPT_ARGS];
315 au_br_perm_str_t attr;
316
317 p = strchr(perm, '+');
318 if (p)
319 *p = 0;
320 val = match_token(perm, brperm, args);
321 if (!val) {
322 if (p)
323 *p = '+';
324 pr_warn("ignored branch permission %s\n", perm);
325 val = AuBrPerm_RO;
326 goto out;
327 }
328 if (!p)
329 goto out;
330
331 val |= br_attr_val(p + 1, brattr, args);
332
333 bad = 0;
334 switch (val & AuBrPerm_Mask) {
335 case AuBrPerm_RO:
336 case AuBrPerm_RR:
337 bad = val & AuBrWAttr_Mask;
338 val &= ~AuBrWAttr_Mask;
339 break;
340 case AuBrPerm_RW:
341 bad = val & AuBrRAttr_Mask;
342 val &= ~AuBrRAttr_Mask;
343 break;
344 }
345
346 /*
347 * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
348 * does not treat it as an error, just warning.
349 * this is a tiny guard for the user operation.
350 */
351 if (val & AuBrAttr_UNPIN) {
352 bad |= AuBrAttr_UNPIN;
353 val &= ~AuBrAttr_UNPIN;
354 }
355
356 if (unlikely(bad)) {
357 sz = au_do_optstr_br_attr(&attr, bad);
358 AuDebugOn(!sz);
359 pr_warn("ignored branch attribute %s\n", attr.a);
360 }
361
362out:
363 return val;
364}
365
366void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
367{
368 au_br_perm_str_t attr;
369 const char *p;
370 char *q;
371 int sz;
372
373 q = str->a;
374 p = au_optstr(&perm, brperm);
375 AuDebugOn(!p || !*p);
376 sz = strlen(p);
377 memcpy(q, p, sz + 1);
378 q += sz;
379
380 sz = au_do_optstr_br_attr(&attr, perm);
381 if (sz) {
382 *q++ = '+';
383 memcpy(q, attr.a, sz + 1);
384 }
385
386 AuDebugOn(strlen(str->a) >= sizeof(str->a));
387}
388
389/* ---------------------------------------------------------------------- */
390
391static match_table_t udbalevel = {
392 {AuOpt_UDBA_REVAL, "reval"},
393 {AuOpt_UDBA_NONE, "none"},
394#ifdef CONFIG_AUFS_HNOTIFY
395 {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
396#ifdef CONFIG_AUFS_HFSNOTIFY
397 {AuOpt_UDBA_HNOTIFY, "fsnotify"},
398#endif
399#endif
400 {-1, NULL}
401};
402
403static int noinline_for_stack udba_val(char *str)
404{
405 substring_t args[MAX_OPT_ARGS];
406
407 return match_token(str, udbalevel, args);
408}
409
410const char *au_optstr_udba(int udba)
411{
412 return au_parser_pattern(udba, udbalevel);
413}
414
415/* ---------------------------------------------------------------------- */
416
417static match_table_t au_wbr_create_policy = {
418 {AuWbrCreate_TDP, "tdp"},
419 {AuWbrCreate_TDP, "top-down-parent"},
420 {AuWbrCreate_RR, "rr"},
421 {AuWbrCreate_RR, "round-robin"},
422 {AuWbrCreate_MFS, "mfs"},
423 {AuWbrCreate_MFS, "most-free-space"},
424 {AuWbrCreate_MFSV, "mfs:%d"},
425 {AuWbrCreate_MFSV, "most-free-space:%d"},
426
427 {AuWbrCreate_MFSRR, "mfsrr:%d"},
428 {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
429 {AuWbrCreate_PMFS, "pmfs"},
430 {AuWbrCreate_PMFSV, "pmfs:%d"},
431 {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
432 {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
433
434 {-1, NULL}
435};
436
437/*
438 * cf. linux/lib/parser.c and cmdline.c
439 * gave up calling memparse() since it uses simple_strtoull() instead of
440 * kstrto...().
441 */
442static int noinline_for_stack
443au_match_ull(substring_t *s, unsigned long long *result)
444{
445 int err;
446 unsigned int len;
447 char a[32];
448
449 err = -ERANGE;
450 len = s->to - s->from;
451 if (len + 1 <= sizeof(a)) {
452 memcpy(a, s->from, len);
453 a[len] = '\0';
454 err = kstrtoull(a, 0, result);
455 }
456 return err;
457}
458
459static int au_wbr_mfs_wmark(substring_t *arg, char *str,
460 struct au_opt_wbr_create *create)
461{
462 int err;
463 unsigned long long ull;
464
465 err = 0;
466 if (!au_match_ull(arg, &ull))
467 create->mfsrr_watermark = ull;
468 else {
469 pr_err("bad integer in %s\n", str);
470 err = -EINVAL;
471 }
472
473 return err;
474}
475
476static int au_wbr_mfs_sec(substring_t *arg, char *str,
477 struct au_opt_wbr_create *create)
478{
479 int n, err;
480
481 err = 0;
482 if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
483 create->mfs_second = n;
484 else {
485 pr_err("bad integer in %s\n", str);
486 err = -EINVAL;
487 }
488
489 return err;
490}
491
492static int noinline_for_stack
493au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
494{
495 int err, e;
496 substring_t args[MAX_OPT_ARGS];
497
498 err = match_token(str, au_wbr_create_policy, args);
499 create->wbr_create = err;
500 switch (err) {
501 case AuWbrCreate_MFSRRV:
502 case AuWbrCreate_PMFSRRV:
503 e = au_wbr_mfs_wmark(&args[0], str, create);
504 if (!e)
505 e = au_wbr_mfs_sec(&args[1], str, create);
506 if (unlikely(e))
507 err = e;
508 break;
509 case AuWbrCreate_MFSRR:
510 case AuWbrCreate_PMFSRR:
511 e = au_wbr_mfs_wmark(&args[0], str, create);
512 if (unlikely(e)) {
513 err = e;
514 break;
515 }
516 /*FALLTHROUGH*/
517 case AuWbrCreate_MFS:
518 case AuWbrCreate_PMFS:
519 create->mfs_second = AUFS_MFS_DEF_SEC;
520 break;
521 case AuWbrCreate_MFSV:
522 case AuWbrCreate_PMFSV:
523 e = au_wbr_mfs_sec(&args[0], str, create);
524 if (unlikely(e))
525 err = e;
526 break;
527 }
528
529 return err;
530}
531
532const char *au_optstr_wbr_create(int wbr_create)
533{
534 return au_parser_pattern(wbr_create, au_wbr_create_policy);
535}
536
537static match_table_t au_wbr_copyup_policy = {
538 {AuWbrCopyup_TDP, "tdp"},
539 {AuWbrCopyup_TDP, "top-down-parent"},
540 {AuWbrCopyup_BUP, "bup"},
541 {AuWbrCopyup_BUP, "bottom-up-parent"},
542 {AuWbrCopyup_BU, "bu"},
543 {AuWbrCopyup_BU, "bottom-up"},
544 {-1, NULL}
545};
546
547static int noinline_for_stack au_wbr_copyup_val(char *str)
548{
549 substring_t args[MAX_OPT_ARGS];
550
551 return match_token(str, au_wbr_copyup_policy, args);
552}
553
554const char *au_optstr_wbr_copyup(int wbr_copyup)
555{
556 return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
557}
558
559/* ---------------------------------------------------------------------- */
560
561static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
562
563static void dump_opts(struct au_opts *opts)
564{
565#ifdef CONFIG_AUFS_DEBUG
566 /* reduce stack space */
567 union {
568 struct au_opt_add *add;
569 struct au_opt_del *del;
570 struct au_opt_mod *mod;
571 struct au_opt_xino *xino;
572 struct au_opt_xino_itrunc *xino_itrunc;
573 struct au_opt_wbr_create *create;
574 } u;
575 struct au_opt *opt;
576
577 opt = opts->opt;
578 while (opt->type != Opt_tail) {
579 switch (opt->type) {
580 case Opt_add:
581 u.add = &opt->add;
582 AuDbg("add {b%d, %s, 0x%x, %p}\n",
583 u.add->bindex, u.add->pathname, u.add->perm,
584 u.add->path.dentry);
585 break;
586 case Opt_del:
587 case Opt_idel:
588 u.del = &opt->del;
589 AuDbg("del {%s, %p}\n",
590 u.del->pathname, u.del->h_path.dentry);
591 break;
592 case Opt_mod:
593 case Opt_imod:
594 u.mod = &opt->mod;
595 AuDbg("mod {%s, 0x%x, %p}\n",
596 u.mod->path, u.mod->perm, u.mod->h_root);
597 break;
598 case Opt_append:
599 u.add = &opt->add;
600 AuDbg("append {b%d, %s, 0x%x, %p}\n",
601 u.add->bindex, u.add->pathname, u.add->perm,
602 u.add->path.dentry);
603 break;
604 case Opt_prepend:
605 u.add = &opt->add;
606 AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
607 u.add->bindex, u.add->pathname, u.add->perm,
608 u.add->path.dentry);
609 break;
610 case Opt_dirwh:
611 AuDbg("dirwh %d\n", opt->dirwh);
612 break;
613 case Opt_rdcache:
614 AuDbg("rdcache %d\n", opt->rdcache);
615 break;
616 case Opt_rdblk:
617 AuDbg("rdblk %u\n", opt->rdblk);
618 break;
619 case Opt_rdblk_def:
620 AuDbg("rdblk_def\n");
621 break;
622 case Opt_rdhash:
623 AuDbg("rdhash %u\n", opt->rdhash);
624 break;
625 case Opt_rdhash_def:
626 AuDbg("rdhash_def\n");
627 break;
628 case Opt_xino:
629 u.xino = &opt->xino;
630 AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
631 break;
632 case Opt_trunc_xino:
633 AuLabel(trunc_xino);
634 break;
635 case Opt_notrunc_xino:
636 AuLabel(notrunc_xino);
637 break;
638 case Opt_trunc_xino_path:
639 case Opt_itrunc_xino:
640 u.xino_itrunc = &opt->xino_itrunc;
641 AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
642 break;
643 case Opt_noxino:
644 AuLabel(noxino);
645 break;
646 case Opt_trunc_xib:
647 AuLabel(trunc_xib);
648 break;
649 case Opt_notrunc_xib:
650 AuLabel(notrunc_xib);
651 break;
652 case Opt_shwh:
653 AuLabel(shwh);
654 break;
655 case Opt_noshwh:
656 AuLabel(noshwh);
657 break;
658 case Opt_dirperm1:
659 AuLabel(dirperm1);
660 break;
661 case Opt_nodirperm1:
662 AuLabel(nodirperm1);
663 break;
664 case Opt_plink:
665 AuLabel(plink);
666 break;
667 case Opt_noplink:
668 AuLabel(noplink);
669 break;
670 case Opt_list_plink:
671 AuLabel(list_plink);
672 break;
673 case Opt_udba:
674 AuDbg("udba %d, %s\n",
675 opt->udba, au_optstr_udba(opt->udba));
676 break;
677 case Opt_dio:
678 AuLabel(dio);
679 break;
680 case Opt_nodio:
681 AuLabel(nodio);
682 break;
683 case Opt_diropq_a:
684 AuLabel(diropq_a);
685 break;
686 case Opt_diropq_w:
687 AuLabel(diropq_w);
688 break;
689 case Opt_warn_perm:
690 AuLabel(warn_perm);
691 break;
692 case Opt_nowarn_perm:
693 AuLabel(nowarn_perm);
694 break;
695 case Opt_verbose:
696 AuLabel(verbose);
697 break;
698 case Opt_noverbose:
699 AuLabel(noverbose);
700 break;
701 case Opt_sum:
702 AuLabel(sum);
703 break;
704 case Opt_nosum:
705 AuLabel(nosum);
706 break;
707 case Opt_wsum:
708 AuLabel(wsum);
709 break;
710 case Opt_wbr_create:
711 u.create = &opt->wbr_create;
712 AuDbg("create %d, %s\n", u.create->wbr_create,
713 au_optstr_wbr_create(u.create->wbr_create));
714 switch (u.create->wbr_create) {
715 case AuWbrCreate_MFSV:
716 case AuWbrCreate_PMFSV:
717 AuDbg("%d sec\n", u.create->mfs_second);
718 break;
719 case AuWbrCreate_MFSRR:
720 AuDbg("%llu watermark\n",
721 u.create->mfsrr_watermark);
722 break;
723 case AuWbrCreate_MFSRRV:
724 case AuWbrCreate_PMFSRRV:
725 AuDbg("%llu watermark, %d sec\n",
726 u.create->mfsrr_watermark,
727 u.create->mfs_second);
728 break;
729 }
730 break;
731 case Opt_wbr_copyup:
732 AuDbg("copyup %d, %s\n", opt->wbr_copyup,
733 au_optstr_wbr_copyup(opt->wbr_copyup));
734 break;
735 case Opt_fhsm_sec:
736 AuDbg("fhsm_sec %u\n", opt->fhsm_second);
737 break;
738 case Opt_acl:
739 AuLabel(acl);
740 break;
741 case Opt_noacl:
742 AuLabel(noacl);
743 break;
744 default:
745 BUG();
746 }
747 opt++;
748 }
749#endif
750}
751
752void au_opts_free(struct au_opts *opts)
753{
754 struct au_opt *opt;
755
756 opt = opts->opt;
757 while (opt->type != Opt_tail) {
758 switch (opt->type) {
759 case Opt_add:
760 case Opt_append:
761 case Opt_prepend:
762 path_put(&opt->add.path);
763 break;
764 case Opt_del:
765 case Opt_idel:
766 path_put(&opt->del.h_path);
767 break;
768 case Opt_mod:
769 case Opt_imod:
770 dput(opt->mod.h_root);
771 break;
772 case Opt_xino:
773 fput(opt->xino.file);
774 break;
775 }
776 opt++;
777 }
778}
779
780static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
781 aufs_bindex_t bindex)
782{
783 int err;
784 struct au_opt_add *add = &opt->add;
785 char *p;
786
787 add->bindex = bindex;
788 add->perm = AuBrPerm_RO;
789 add->pathname = opt_str;
790 p = strchr(opt_str, '=');
791 if (p) {
792 *p++ = 0;
793 if (*p)
794 add->perm = br_perm_val(p);
795 }
796
797 err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
798 if (!err) {
799 if (!p) {
800 add->perm = AuBrPerm_RO;
801 if (au_test_fs_rr(add->path.dentry->d_sb))
802 add->perm = AuBrPerm_RR;
803 else if (!bindex && !(sb_flags & MS_RDONLY))
804 add->perm = AuBrPerm_RW;
805 }
806 opt->type = Opt_add;
807 goto out;
808 }
809 pr_err("lookup failed %s (%d)\n", add->pathname, err);
810 err = -EINVAL;
811
812out:
813 return err;
814}
815
816static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
817{
818 int err;
819
820 del->pathname = args[0].from;
821 AuDbg("del path %s\n", del->pathname);
822
823 err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
824 if (unlikely(err))
825 pr_err("lookup failed %s (%d)\n", del->pathname, err);
826
827 return err;
828}
829
830#if 0 /* reserved for future use */
831static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
832 struct au_opt_del *del, substring_t args[])
833{
834 int err;
835 struct dentry *root;
836
837 err = -EINVAL;
838 root = sb->s_root;
839 aufs_read_lock(root, AuLock_FLUSH);
840 if (bindex < 0 || au_sbbot(sb) < bindex) {
841 pr_err("out of bounds, %d\n", bindex);
842 goto out;
843 }
844
845 err = 0;
846 del->h_path.dentry = dget(au_h_dptr(root, bindex));
847 del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
848
849out:
850 aufs_read_unlock(root, !AuLock_IR);
851 return err;
852}
853#endif
854
855static int noinline_for_stack
856au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
857{
858 int err;
859 struct path path;
860 char *p;
861
862 err = -EINVAL;
863 mod->path = args[0].from;
864 p = strchr(mod->path, '=');
865 if (unlikely(!p)) {
866 pr_err("no permssion %s\n", args[0].from);
867 goto out;
868 }
869
870 *p++ = 0;
871 err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
872 if (unlikely(err)) {
873 pr_err("lookup failed %s (%d)\n", mod->path, err);
874 goto out;
875 }
876
877 mod->perm = br_perm_val(p);
878 AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
879 mod->h_root = dget(path.dentry);
880 path_put(&path);
881
882out:
883 return err;
884}
885
886#if 0 /* reserved for future use */
887static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
888 struct au_opt_mod *mod, substring_t args[])
889{
890 int err;
891 struct dentry *root;
892
893 err = -EINVAL;
894 root = sb->s_root;
895 aufs_read_lock(root, AuLock_FLUSH);
896 if (bindex < 0 || au_sbbot(sb) < bindex) {
897 pr_err("out of bounds, %d\n", bindex);
898 goto out;
899 }
900
901 err = 0;
902 mod->perm = br_perm_val(args[1].from);
903 AuDbg("mod path %s, perm 0x%x, %s\n",
904 mod->path, mod->perm, args[1].from);
905 mod->h_root = dget(au_h_dptr(root, bindex));
906
907out:
908 aufs_read_unlock(root, !AuLock_IR);
909 return err;
910}
911#endif
912
913static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
914 substring_t args[])
915{
916 int err;
917 struct file *file;
918
919 file = au_xino_create(sb, args[0].from, /*silent*/0);
920 err = PTR_ERR(file);
921 if (IS_ERR(file))
922 goto out;
923
924 err = -EINVAL;
925 if (unlikely(file->f_path.dentry->d_sb == sb)) {
926 fput(file);
927 pr_err("%s must be outside\n", args[0].from);
928 goto out;
929 }
930
931 err = 0;
932 xino->file = file;
933 xino->path = args[0].from;
934
935out:
936 return err;
937}
938
939static int noinline_for_stack
940au_opts_parse_xino_itrunc_path(struct super_block *sb,
941 struct au_opt_xino_itrunc *xino_itrunc,
942 substring_t args[])
943{
944 int err;
945 aufs_bindex_t bbot, bindex;
946 struct path path;
947 struct dentry *root;
948
949 err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
950 if (unlikely(err)) {
951 pr_err("lookup failed %s (%d)\n", args[0].from, err);
952 goto out;
953 }
954
955 xino_itrunc->bindex = -1;
956 root = sb->s_root;
957 aufs_read_lock(root, AuLock_FLUSH);
958 bbot = au_sbbot(sb);
959 for (bindex = 0; bindex <= bbot; bindex++) {
960 if (au_h_dptr(root, bindex) == path.dentry) {
961 xino_itrunc->bindex = bindex;
962 break;
963 }
964 }
965 aufs_read_unlock(root, !AuLock_IR);
966 path_put(&path);
967
968 if (unlikely(xino_itrunc->bindex < 0)) {
969 pr_err("no such branch %s\n", args[0].from);
970 err = -EINVAL;
971 }
972
973out:
974 return err;
975}
976
977/* called without aufs lock */
978int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
979{
980 int err, n, token;
981 aufs_bindex_t bindex;
982 unsigned char skipped;
983 struct dentry *root;
984 struct au_opt *opt, *opt_tail;
985 char *opt_str;
986 /* reduce the stack space */
987 union {
988 struct au_opt_xino_itrunc *xino_itrunc;
989 struct au_opt_wbr_create *create;
990 } u;
991 struct {
992 substring_t args[MAX_OPT_ARGS];
993 } *a;
994
995 err = -ENOMEM;
996 a = kmalloc(sizeof(*a), GFP_NOFS);
997 if (unlikely(!a))
998 goto out;
999
1000 root = sb->s_root;
1001 err = 0;
1002 bindex = 0;
1003 opt = opts->opt;
1004 opt_tail = opt + opts->max_opt - 1;
1005 opt->type = Opt_tail;
1006 while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
1007 err = -EINVAL;
1008 skipped = 0;
1009 token = match_token(opt_str, options, a->args);
1010 switch (token) {
1011 case Opt_br:
1012 err = 0;
1013 while (!err && (opt_str = strsep(&a->args[0].from, ":"))
1014 && *opt_str) {
1015 err = opt_add(opt, opt_str, opts->sb_flags,
1016 bindex++);
1017 if (unlikely(!err && ++opt > opt_tail)) {
1018 err = -E2BIG;
1019 break;
1020 }
1021 opt->type = Opt_tail;
1022 skipped = 1;
1023 }
1024 break;
1025 case Opt_add:
1026 if (unlikely(match_int(&a->args[0], &n))) {
1027 pr_err("bad integer in %s\n", opt_str);
1028 break;
1029 }
1030 bindex = n;
1031 err = opt_add(opt, a->args[1].from, opts->sb_flags,
1032 bindex);
1033 if (!err)
1034 opt->type = token;
1035 break;
1036 case Opt_append:
1037 err = opt_add(opt, a->args[0].from, opts->sb_flags,
1038 /*dummy bindex*/1);
1039 if (!err)
1040 opt->type = token;
1041 break;
1042 case Opt_prepend:
1043 err = opt_add(opt, a->args[0].from, opts->sb_flags,
1044 /*bindex*/0);
1045 if (!err)
1046 opt->type = token;
1047 break;
1048 case Opt_del:
1049 err = au_opts_parse_del(&opt->del, a->args);
1050 if (!err)
1051 opt->type = token;
1052 break;
1053#if 0 /* reserved for future use */
1054 case Opt_idel:
1055 del->pathname = "(indexed)";
1056 if (unlikely(match_int(&args[0], &n))) {
1057 pr_err("bad integer in %s\n", opt_str);
1058 break;
1059 }
1060 err = au_opts_parse_idel(sb, n, &opt->del, a->args);
1061 if (!err)
1062 opt->type = token;
1063 break;
1064#endif
1065 case Opt_mod:
1066 err = au_opts_parse_mod(&opt->mod, a->args);
1067 if (!err)
1068 opt->type = token;
1069 break;
1070#ifdef IMOD /* reserved for future use */
1071 case Opt_imod:
1072 u.mod->path = "(indexed)";
1073 if (unlikely(match_int(&a->args[0], &n))) {
1074 pr_err("bad integer in %s\n", opt_str);
1075 break;
1076 }
1077 err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
1078 if (!err)
1079 opt->type = token;
1080 break;
1081#endif
1082 case Opt_xino:
1083 err = au_opts_parse_xino(sb, &opt->xino, a->args);
1084 if (!err)
1085 opt->type = token;
1086 break;
1087
1088 case Opt_trunc_xino_path:
1089 err = au_opts_parse_xino_itrunc_path
1090 (sb, &opt->xino_itrunc, a->args);
1091 if (!err)
1092 opt->type = token;
1093 break;
1094
1095 case Opt_itrunc_xino:
1096 u.xino_itrunc = &opt->xino_itrunc;
1097 if (unlikely(match_int(&a->args[0], &n))) {
1098 pr_err("bad integer in %s\n", opt_str);
1099 break;
1100 }
1101 u.xino_itrunc->bindex = n;
1102 aufs_read_lock(root, AuLock_FLUSH);
1103 if (n < 0 || au_sbbot(sb) < n) {
1104 pr_err("out of bounds, %d\n", n);
1105 aufs_read_unlock(root, !AuLock_IR);
1106 break;
1107 }
1108 aufs_read_unlock(root, !AuLock_IR);
1109 err = 0;
1110 opt->type = token;
1111 break;
1112
1113 case Opt_dirwh:
1114 if (unlikely(match_int(&a->args[0], &opt->dirwh)))
1115 break;
1116 err = 0;
1117 opt->type = token;
1118 break;
1119
1120 case Opt_rdcache:
1121 if (unlikely(match_int(&a->args[0], &n))) {
1122 pr_err("bad integer in %s\n", opt_str);
1123 break;
1124 }
1125 if (unlikely(n > AUFS_RDCACHE_MAX)) {
1126 pr_err("rdcache must be smaller than %d\n",
1127 AUFS_RDCACHE_MAX);
1128 break;
1129 }
1130 opt->rdcache = n;
1131 err = 0;
1132 opt->type = token;
1133 break;
1134 case Opt_rdblk:
1135 if (unlikely(match_int(&a->args[0], &n)
1136 || n < 0
1137 || n > KMALLOC_MAX_SIZE)) {
1138 pr_err("bad integer in %s\n", opt_str);
1139 break;
1140 }
1141 if (unlikely(n && n < NAME_MAX)) {
1142 pr_err("rdblk must be larger than %d\n",
1143 NAME_MAX);
1144 break;
1145 }
1146 opt->rdblk = n;
1147 err = 0;
1148 opt->type = token;
1149 break;
1150 case Opt_rdhash:
1151 if (unlikely(match_int(&a->args[0], &n)
1152 || n < 0
1153 || n * sizeof(struct hlist_head)
1154 > KMALLOC_MAX_SIZE)) {
1155 pr_err("bad integer in %s\n", opt_str);
1156 break;
1157 }
1158 opt->rdhash = n;
1159 err = 0;
1160 opt->type = token;
1161 break;
1162
1163 case Opt_trunc_xino:
1164 case Opt_notrunc_xino:
1165 case Opt_noxino:
1166 case Opt_trunc_xib:
1167 case Opt_notrunc_xib:
1168 case Opt_shwh:
1169 case Opt_noshwh:
1170 case Opt_dirperm1:
1171 case Opt_nodirperm1:
1172 case Opt_plink:
1173 case Opt_noplink:
1174 case Opt_list_plink:
1175 case Opt_dio:
1176 case Opt_nodio:
1177 case Opt_diropq_a:
1178 case Opt_diropq_w:
1179 case Opt_warn_perm:
1180 case Opt_nowarn_perm:
1181 case Opt_verbose:
1182 case Opt_noverbose:
1183 case Opt_sum:
1184 case Opt_nosum:
1185 case Opt_wsum:
1186 case Opt_rdblk_def:
1187 case Opt_rdhash_def:
1188 case Opt_acl:
1189 case Opt_noacl:
1190 err = 0;
1191 opt->type = token;
1192 break;
1193
1194 case Opt_udba:
1195 opt->udba = udba_val(a->args[0].from);
1196 if (opt->udba >= 0) {
1197 err = 0;
1198 opt->type = token;
1199 } else
1200 pr_err("wrong value, %s\n", opt_str);
1201 break;
1202
1203 case Opt_wbr_create:
1204 u.create = &opt->wbr_create;
1205 u.create->wbr_create
1206 = au_wbr_create_val(a->args[0].from, u.create);
1207 if (u.create->wbr_create >= 0) {
1208 err = 0;
1209 opt->type = token;
1210 } else
1211 pr_err("wrong value, %s\n", opt_str);
1212 break;
1213 case Opt_wbr_copyup:
1214 opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
1215 if (opt->wbr_copyup >= 0) {
1216 err = 0;
1217 opt->type = token;
1218 } else
1219 pr_err("wrong value, %s\n", opt_str);
1220 break;
1221
1222 case Opt_fhsm_sec:
1223 if (unlikely(match_int(&a->args[0], &n)
1224 || n < 0)) {
1225 pr_err("bad integer in %s\n", opt_str);
1226 break;
1227 }
1228 if (sysaufs_brs) {
1229 opt->fhsm_second = n;
1230 opt->type = token;
1231 } else
1232 pr_warn("ignored %s\n", opt_str);
1233 err = 0;
1234 break;
1235
1236 case Opt_ignore:
1237 pr_warn("ignored %s\n", opt_str);
1238 /*FALLTHROUGH*/
1239 case Opt_ignore_silent:
1240 skipped = 1;
1241 err = 0;
1242 break;
1243 case Opt_err:
1244 pr_err("unknown option %s\n", opt_str);
1245 break;
1246 }
1247
1248 if (!err && !skipped) {
1249 if (unlikely(++opt > opt_tail)) {
1250 err = -E2BIG;
1251 opt--;
1252 opt->type = Opt_tail;
1253 break;
1254 }
1255 opt->type = Opt_tail;
1256 }
1257 }
1258
1259 au_delayed_kfree(a);
1260 dump_opts(opts);
1261 if (unlikely(err))
1262 au_opts_free(opts);
1263
1264out:
1265 return err;
1266}
1267
1268static int au_opt_wbr_create(struct super_block *sb,
1269 struct au_opt_wbr_create *create)
1270{
1271 int err;
1272 struct au_sbinfo *sbinfo;
1273
1274 SiMustWriteLock(sb);
1275
1276 err = 1; /* handled */
1277 sbinfo = au_sbi(sb);
1278 if (sbinfo->si_wbr_create_ops->fin) {
1279 err = sbinfo->si_wbr_create_ops->fin(sb);
1280 if (!err)
1281 err = 1;
1282 }
1283
1284 sbinfo->si_wbr_create = create->wbr_create;
1285 sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
1286 switch (create->wbr_create) {
1287 case AuWbrCreate_MFSRRV:
1288 case AuWbrCreate_MFSRR:
1289 case AuWbrCreate_PMFSRR:
1290 case AuWbrCreate_PMFSRRV:
1291 sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
1292 /*FALLTHROUGH*/
1293 case AuWbrCreate_MFS:
1294 case AuWbrCreate_MFSV:
1295 case AuWbrCreate_PMFS:
1296 case AuWbrCreate_PMFSV:
1297 sbinfo->si_wbr_mfs.mfs_expire
1298 = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1299 break;
1300 }
1301
1302 if (sbinfo->si_wbr_create_ops->init)
1303 sbinfo->si_wbr_create_ops->init(sb); /* ignore */
1304
1305 return err;
1306}
1307
1308/*
1309 * returns,
1310 * plus: processed without an error
1311 * zero: unprocessed
1312 */
1313static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
1314 struct au_opts *opts)
1315{
1316 int err;
1317 struct au_sbinfo *sbinfo;
1318
1319 SiMustWriteLock(sb);
1320
1321 err = 1; /* handled */
1322 sbinfo = au_sbi(sb);
1323 switch (opt->type) {
1324 case Opt_udba:
1325 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1326 sbinfo->si_mntflags |= opt->udba;
1327 opts->given_udba |= opt->udba;
1328 break;
1329
1330 case Opt_plink:
1331 au_opt_set(sbinfo->si_mntflags, PLINK);
1332 break;
1333 case Opt_noplink:
1334 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1335 au_plink_put(sb, /*verbose*/1);
1336 au_opt_clr(sbinfo->si_mntflags, PLINK);
1337 break;
1338 case Opt_list_plink:
1339 if (au_opt_test(sbinfo->si_mntflags, PLINK))
1340 au_plink_list(sb);
1341 break;
1342
1343 case Opt_dio:
1344 au_opt_set(sbinfo->si_mntflags, DIO);
1345 au_fset_opts(opts->flags, REFRESH_DYAOP);
1346 break;
1347 case Opt_nodio:
1348 au_opt_clr(sbinfo->si_mntflags, DIO);
1349 au_fset_opts(opts->flags, REFRESH_DYAOP);
1350 break;
1351
1352 case Opt_fhsm_sec:
1353 au_fhsm_set(sbinfo, opt->fhsm_second);
1354 break;
1355
1356 case Opt_diropq_a:
1357 au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1358 break;
1359 case Opt_diropq_w:
1360 au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
1361 break;
1362
1363 case Opt_warn_perm:
1364 au_opt_set(sbinfo->si_mntflags, WARN_PERM);
1365 break;
1366 case Opt_nowarn_perm:
1367 au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
1368 break;
1369
1370 case Opt_verbose:
1371 au_opt_set(sbinfo->si_mntflags, VERBOSE);
1372 break;
1373 case Opt_noverbose:
1374 au_opt_clr(sbinfo->si_mntflags, VERBOSE);
1375 break;
1376
1377 case Opt_sum:
1378 au_opt_set(sbinfo->si_mntflags, SUM);
1379 break;
1380 case Opt_wsum:
1381 au_opt_clr(sbinfo->si_mntflags, SUM);
1382 au_opt_set(sbinfo->si_mntflags, SUM_W);
1383 case Opt_nosum:
1384 au_opt_clr(sbinfo->si_mntflags, SUM);
1385 au_opt_clr(sbinfo->si_mntflags, SUM_W);
1386 break;
1387
1388 case Opt_wbr_create:
1389 err = au_opt_wbr_create(sb, &opt->wbr_create);
1390 break;
1391 case Opt_wbr_copyup:
1392 sbinfo->si_wbr_copyup = opt->wbr_copyup;
1393 sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
1394 break;
1395
1396 case Opt_dirwh:
1397 sbinfo->si_dirwh = opt->dirwh;
1398 break;
1399
1400 case Opt_rdcache:
1401 sbinfo->si_rdcache
1402 = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1403 break;
1404 case Opt_rdblk:
1405 sbinfo->si_rdblk = opt->rdblk;
1406 break;
1407 case Opt_rdblk_def:
1408 sbinfo->si_rdblk = AUFS_RDBLK_DEF;
1409 break;
1410 case Opt_rdhash:
1411 sbinfo->si_rdhash = opt->rdhash;
1412 break;
1413 case Opt_rdhash_def:
1414 sbinfo->si_rdhash = AUFS_RDHASH_DEF;
1415 break;
1416
1417 case Opt_shwh:
1418 au_opt_set(sbinfo->si_mntflags, SHWH);
1419 break;
1420 case Opt_noshwh:
1421 au_opt_clr(sbinfo->si_mntflags, SHWH);
1422 break;
1423
1424 case Opt_dirperm1:
1425 au_opt_set(sbinfo->si_mntflags, DIRPERM1);
1426 break;
1427 case Opt_nodirperm1:
1428 au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
1429 break;
1430
1431 case Opt_trunc_xino:
1432 au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
1433 break;
1434 case Opt_notrunc_xino:
1435 au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
1436 break;
1437
1438 case Opt_trunc_xino_path:
1439 case Opt_itrunc_xino:
1440 err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
1441 if (!err)
1442 err = 1;
1443 break;
1444
1445 case Opt_trunc_xib:
1446 au_fset_opts(opts->flags, TRUNC_XIB);
1447 break;
1448 case Opt_notrunc_xib:
1449 au_fclr_opts(opts->flags, TRUNC_XIB);
1450 break;
1451
1452 case Opt_acl:
1453 sb->s_flags |= MS_POSIXACL;
1454 break;
1455 case Opt_noacl:
1456 sb->s_flags &= ~MS_POSIXACL;
1457 break;
1458
1459 default:
1460 err = 0;
1461 break;
1462 }
1463
1464 return err;
1465}
1466
1467/*
1468 * returns tri-state.
1469 * plus: processed without an error
1470 * zero: unprocessed
1471 * minus: error
1472 */
1473static int au_opt_br(struct super_block *sb, struct au_opt *opt,
1474 struct au_opts *opts)
1475{
1476 int err, do_refresh;
1477
1478 err = 0;
1479 switch (opt->type) {
1480 case Opt_append:
1481 opt->add.bindex = au_sbbot(sb) + 1;
1482 if (opt->add.bindex < 0)
1483 opt->add.bindex = 0;
1484 goto add;
1485 case Opt_prepend:
1486 opt->add.bindex = 0;
1487 add: /* indented label */
1488 case Opt_add:
1489 err = au_br_add(sb, &opt->add,
1490 au_ftest_opts(opts->flags, REMOUNT));
1491 if (!err) {
1492 err = 1;
1493 au_fset_opts(opts->flags, REFRESH);
1494 }
1495 break;
1496
1497 case Opt_del:
1498 case Opt_idel:
1499 err = au_br_del(sb, &opt->del,
1500 au_ftest_opts(opts->flags, REMOUNT));
1501 if (!err) {
1502 err = 1;
1503 au_fset_opts(opts->flags, TRUNC_XIB);
1504 au_fset_opts(opts->flags, REFRESH);
1505 }
1506 break;
1507
1508 case Opt_mod:
1509 case Opt_imod:
1510 err = au_br_mod(sb, &opt->mod,
1511 au_ftest_opts(opts->flags, REMOUNT),
1512 &do_refresh);
1513 if (!err) {
1514 err = 1;
1515 if (do_refresh)
1516 au_fset_opts(opts->flags, REFRESH);
1517 }
1518 break;
1519 }
1520
1521 return err;
1522}
1523
1524static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
1525 struct au_opt_xino **opt_xino,
1526 struct au_opts *opts)
1527{
1528 int err;
1529 aufs_bindex_t bbot, bindex;
1530 struct dentry *root, *parent, *h_root;
1531
1532 err = 0;
1533 switch (opt->type) {
1534 case Opt_xino:
1535 err = au_xino_set(sb, &opt->xino,
1536 !!au_ftest_opts(opts->flags, REMOUNT));
1537 if (unlikely(err))
1538 break;
1539
1540 *opt_xino = &opt->xino;
1541 au_xino_brid_set(sb, -1);
1542
1543 /* safe d_parent access */
1544 parent = opt->xino.file->f_path.dentry->d_parent;
1545 root = sb->s_root;
1546 bbot = au_sbbot(sb);
1547 for (bindex = 0; bindex <= bbot; bindex++) {
1548 h_root = au_h_dptr(root, bindex);
1549 if (h_root == parent) {
1550 au_xino_brid_set(sb, au_sbr_id(sb, bindex));
1551 break;
1552 }
1553 }
1554 break;
1555
1556 case Opt_noxino:
1557 au_xino_clr(sb);
1558 au_xino_brid_set(sb, -1);
1559 *opt_xino = (void *)-1;
1560 break;
1561 }
1562
1563 return err;
1564}
1565
1566int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
1567 unsigned int pending)
1568{
1569 int err, fhsm;
1570 aufs_bindex_t bindex, bbot;
1571 unsigned char do_plink, skip, do_free, can_no_dreval;
1572 struct au_branch *br;
1573 struct au_wbr *wbr;
1574 struct dentry *root, *dentry;
1575 struct inode *dir, *h_dir;
1576 struct au_sbinfo *sbinfo;
1577 struct au_hinode *hdir;
1578
1579 SiMustAnyLock(sb);
1580
1581 sbinfo = au_sbi(sb);
1582 AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
1583
1584 if (!(sb_flags & MS_RDONLY)) {
1585 if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
1586 pr_warn("first branch should be rw\n");
1587 if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
1588 pr_warn_once("shwh should be used with ro\n");
1589 }
1590
1591 if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1592 && !au_opt_test(sbinfo->si_mntflags, XINO))
1593 pr_warn_once("udba=*notify requires xino\n");
1594
1595 if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
1596 pr_warn_once("dirperm1 breaks the protection"
1597 " by the permission bits on the lower branch\n");
1598
1599 err = 0;
1600 fhsm = 0;
1601 root = sb->s_root;
1602 dir = d_inode(root);
1603 do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
1604 can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
1605 UDBA_NONE);
1606 bbot = au_sbbot(sb);
1607 for (bindex = 0; !err && bindex <= bbot; bindex++) {
1608 skip = 0;
1609 h_dir = au_h_iptr(dir, bindex);
1610 br = au_sbr(sb, bindex);
1611
1612 if ((br->br_perm & AuBrAttr_ICEX)
1613 && !h_dir->i_op->listxattr)
1614 br->br_perm &= ~AuBrAttr_ICEX;
1615#if 0
1616 if ((br->br_perm & AuBrAttr_ICEX_SEC)
1617 && (au_br_sb(br)->s_flags & MS_NOSEC))
1618 br->br_perm &= ~AuBrAttr_ICEX_SEC;
1619#endif
1620
1621 do_free = 0;
1622 wbr = br->br_wbr;
1623 if (wbr)
1624 wbr_wh_read_lock(wbr);
1625
1626 if (!au_br_writable(br->br_perm)) {
1627 do_free = !!wbr;
1628 skip = (!wbr
1629 || (!wbr->wbr_whbase
1630 && !wbr->wbr_plink
1631 && !wbr->wbr_orph));
1632 } else if (!au_br_wh_linkable(br->br_perm)) {
1633 /* skip = (!br->br_whbase && !br->br_orph); */
1634 skip = (!wbr || !wbr->wbr_whbase);
1635 if (skip && wbr) {
1636 if (do_plink)
1637 skip = !!wbr->wbr_plink;
1638 else
1639 skip = !wbr->wbr_plink;
1640 }
1641 } else {
1642 /* skip = (br->br_whbase && br->br_ohph); */
1643 skip = (wbr && wbr->wbr_whbase);
1644 if (skip) {
1645 if (do_plink)
1646 skip = !!wbr->wbr_plink;
1647 else
1648 skip = !wbr->wbr_plink;
1649 }
1650 }
1651 if (wbr)
1652 wbr_wh_read_unlock(wbr);
1653
1654 if (can_no_dreval) {
1655 dentry = br->br_path.dentry;
1656 spin_lock(&dentry->d_lock);
1657 if (dentry->d_flags &
1658 (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
1659 can_no_dreval = 0;
1660 spin_unlock(&dentry->d_lock);
1661 }
1662
1663 if (au_br_fhsm(br->br_perm)) {
1664 fhsm++;
1665 AuDebugOn(!br->br_fhsm);
1666 }
1667
1668 if (skip)
1669 continue;
1670
1671 hdir = au_hi(dir, bindex);
1672 au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1673 if (wbr)
1674 wbr_wh_write_lock(wbr);
1675 err = au_wh_init(br, sb);
1676 if (wbr)
1677 wbr_wh_write_unlock(wbr);
1678 au_hn_inode_unlock(hdir);
1679
1680 if (!err && do_free) {
1681 if (wbr)
1682 au_delayed_kfree(wbr);
1683 br->br_wbr = NULL;
1684 }
1685 }
1686
1687 if (can_no_dreval)
1688 au_fset_si(sbinfo, NO_DREVAL);
1689 else
1690 au_fclr_si(sbinfo, NO_DREVAL);
1691
1692 if (fhsm >= 2) {
1693 au_fset_si(sbinfo, FHSM);
1694 for (bindex = bbot; bindex >= 0; bindex--) {
1695 br = au_sbr(sb, bindex);
1696 if (au_br_fhsm(br->br_perm)) {
1697 au_fhsm_set_bottom(sb, bindex);
1698 break;
1699 }
1700 }
1701 } else {
1702 au_fclr_si(sbinfo, FHSM);
1703 au_fhsm_set_bottom(sb, -1);
1704 }
1705
1706 return err;
1707}
1708
1709int au_opts_mount(struct super_block *sb, struct au_opts *opts)
1710{
1711 int err;
1712 unsigned int tmp;
1713 aufs_bindex_t bindex, bbot;
1714 struct au_opt *opt;
1715 struct au_opt_xino *opt_xino, xino;
1716 struct au_sbinfo *sbinfo;
1717 struct au_branch *br;
1718 struct inode *dir;
1719
1720 SiMustWriteLock(sb);
1721
1722 err = 0;
1723 opt_xino = NULL;
1724 opt = opts->opt;
1725 while (err >= 0 && opt->type != Opt_tail)
1726 err = au_opt_simple(sb, opt++, opts);
1727 if (err > 0)
1728 err = 0;
1729 else if (unlikely(err < 0))
1730 goto out;
1731
1732 /* disable xino and udba temporary */
1733 sbinfo = au_sbi(sb);
1734 tmp = sbinfo->si_mntflags;
1735 au_opt_clr(sbinfo->si_mntflags, XINO);
1736 au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
1737
1738 opt = opts->opt;
1739 while (err >= 0 && opt->type != Opt_tail)
1740 err = au_opt_br(sb, opt++, opts);
1741 if (err > 0)
1742 err = 0;
1743 else if (unlikely(err < 0))
1744 goto out;
1745
1746 bbot = au_sbbot(sb);
1747 if (unlikely(bbot < 0)) {
1748 err = -EINVAL;
1749 pr_err("no branches\n");
1750 goto out;
1751 }
1752
1753 if (au_opt_test(tmp, XINO))
1754 au_opt_set(sbinfo->si_mntflags, XINO);
1755 opt = opts->opt;
1756 while (!err && opt->type != Opt_tail)
1757 err = au_opt_xino(sb, opt++, &opt_xino, opts);
1758 if (unlikely(err))
1759 goto out;
1760
1761 err = au_opts_verify(sb, sb->s_flags, tmp);
1762 if (unlikely(err))
1763 goto out;
1764
1765 /* restore xino */
1766 if (au_opt_test(tmp, XINO) && !opt_xino) {
1767 xino.file = au_xino_def(sb);
1768 err = PTR_ERR(xino.file);
1769 if (IS_ERR(xino.file))
1770 goto out;
1771
1772 err = au_xino_set(sb, &xino, /*remount*/0);
1773 fput(xino.file);
1774 if (unlikely(err))
1775 goto out;
1776 }
1777
1778 /* restore udba */
1779 tmp &= AuOptMask_UDBA;
1780 sbinfo->si_mntflags &= ~AuOptMask_UDBA;
1781 sbinfo->si_mntflags |= tmp;
1782 bbot = au_sbbot(sb);
1783 for (bindex = 0; bindex <= bbot; bindex++) {
1784 br = au_sbr(sb, bindex);
1785 err = au_hnotify_reset_br(tmp, br, br->br_perm);
1786 if (unlikely(err))
1787 AuIOErr("hnotify failed on br %d, %d, ignored\n",
1788 bindex, err);
1789 /* go on even if err */
1790 }
1791 if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1792 dir = d_inode(sb->s_root);
1793 au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1794 }
1795
1796out:
1797 return err;
1798}
1799
1800int au_opts_remount(struct super_block *sb, struct au_opts *opts)
1801{
1802 int err, rerr;
1803 unsigned char no_dreval;
1804 struct inode *dir;
1805 struct au_opt_xino *opt_xino;
1806 struct au_opt *opt;
1807 struct au_sbinfo *sbinfo;
1808
1809 SiMustWriteLock(sb);
1810
1811 err = 0;
1812 dir = d_inode(sb->s_root);
1813 sbinfo = au_sbi(sb);
1814 opt_xino = NULL;
1815 opt = opts->opt;
1816 while (err >= 0 && opt->type != Opt_tail) {
1817 err = au_opt_simple(sb, opt, opts);
1818 if (!err)
1819 err = au_opt_br(sb, opt, opts);
1820 if (!err)
1821 err = au_opt_xino(sb, opt, &opt_xino, opts);
1822 opt++;
1823 }
1824 if (err > 0)
1825 err = 0;
1826 AuTraceErr(err);
1827 /* go on even err */
1828
1829 no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1830 rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
1831 if (unlikely(rerr && !err))
1832 err = rerr;
1833
1834 if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
1835 au_fset_opts(opts->flags, REFRESH_IDOP);
1836
1837 if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
1838 rerr = au_xib_trunc(sb);
1839 if (unlikely(rerr && !err))
1840 err = rerr;
1841 }
1842
1843 /* will be handled by the caller */
1844 if (!au_ftest_opts(opts->flags, REFRESH)
1845 && (opts->given_udba
1846 || au_opt_test(sbinfo->si_mntflags, XINO)
1847 || au_ftest_opts(opts->flags, REFRESH_IDOP)
1848 ))
1849 au_fset_opts(opts->flags, REFRESH);
1850
1851 AuDbg("status 0x%x\n", opts->flags);
1852 return err;
1853}
1854
1855/* ---------------------------------------------------------------------- */
1856
1857unsigned int au_opt_udba(struct super_block *sb)
1858{
1859 return au_mntflags(sb) & AuOptMask_UDBA;
1860}