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