]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/wbr_policy.c
UBUNTU: ubuntu: vbox -- update to 5.2.6-dfsg-5
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / wbr_policy.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 * policies for selecting one among multiple writable branches
20 */
21
22 #include <linux/statfs.h>
23 #include "aufs.h"
24
25 /* subset of cpup_attr() */
26 static noinline_for_stack
27 int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
28 {
29 int err, sbits;
30 struct iattr ia;
31 struct inode *h_isrc;
32
33 h_isrc = d_inode(h_src);
34 ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
35 ia.ia_mode = h_isrc->i_mode;
36 ia.ia_uid = h_isrc->i_uid;
37 ia.ia_gid = h_isrc->i_gid;
38 sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
39 au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
40 /* no delegation since it is just created */
41 err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
42
43 /* is this nfs only? */
44 if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
45 ia.ia_valid = ATTR_FORCE | ATTR_MODE;
46 ia.ia_mode = h_isrc->i_mode;
47 err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
48 }
49
50 return err;
51 }
52
53 #define AuCpdown_PARENT_OPQ 1
54 #define AuCpdown_WHED (1 << 1)
55 #define AuCpdown_MADE_DIR (1 << 2)
56 #define AuCpdown_DIROPQ (1 << 3)
57 #define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
58 #define au_fset_cpdown(flags, name) \
59 do { (flags) |= AuCpdown_##name; } while (0)
60 #define au_fclr_cpdown(flags, name) \
61 do { (flags) &= ~AuCpdown_##name; } while (0)
62
63 static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
64 unsigned int *flags)
65 {
66 int err;
67 struct dentry *opq_dentry;
68
69 opq_dentry = au_diropq_create(dentry, bdst);
70 err = PTR_ERR(opq_dentry);
71 if (IS_ERR(opq_dentry))
72 goto out;
73 dput(opq_dentry);
74 au_fset_cpdown(*flags, DIROPQ);
75
76 out:
77 return err;
78 }
79
80 static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
81 struct inode *dir, aufs_bindex_t bdst)
82 {
83 int err;
84 struct path h_path;
85 struct au_branch *br;
86
87 br = au_sbr(dentry->d_sb, bdst);
88 h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
89 err = PTR_ERR(h_path.dentry);
90 if (IS_ERR(h_path.dentry))
91 goto out;
92
93 err = 0;
94 if (d_is_positive(h_path.dentry)) {
95 h_path.mnt = au_br_mnt(br);
96 err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
97 dentry);
98 }
99 dput(h_path.dentry);
100
101 out:
102 return err;
103 }
104
105 static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
106 struct au_pin *pin,
107 struct dentry *h_parent, void *arg)
108 {
109 int err, rerr;
110 aufs_bindex_t bopq, btop;
111 struct path h_path;
112 struct dentry *parent;
113 struct inode *h_dir, *h_inode, *inode, *dir;
114 unsigned int *flags = arg;
115
116 btop = au_dbtop(dentry);
117 /* dentry is di-locked */
118 parent = dget_parent(dentry);
119 dir = d_inode(parent);
120 h_dir = d_inode(h_parent);
121 AuDebugOn(h_dir != au_h_iptr(dir, bdst));
122 IMustLock(h_dir);
123
124 err = au_lkup_neg(dentry, bdst, /*wh*/0);
125 if (unlikely(err < 0))
126 goto out;
127 h_path.dentry = au_h_dptr(dentry, bdst);
128 h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
129 err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
130 S_IRWXU | S_IRUGO | S_IXUGO);
131 if (unlikely(err))
132 goto out_put;
133 au_fset_cpdown(*flags, MADE_DIR);
134
135 bopq = au_dbdiropq(dentry);
136 au_fclr_cpdown(*flags, WHED);
137 au_fclr_cpdown(*flags, DIROPQ);
138 if (au_dbwh(dentry) == bdst)
139 au_fset_cpdown(*flags, WHED);
140 if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
141 au_fset_cpdown(*flags, PARENT_OPQ);
142 h_inode = d_inode(h_path.dentry);
143 inode_lock_nested(h_inode, AuLsc_I_CHILD);
144 if (au_ftest_cpdown(*flags, WHED)) {
145 err = au_cpdown_dir_opq(dentry, bdst, flags);
146 if (unlikely(err)) {
147 inode_unlock(h_inode);
148 goto out_dir;
149 }
150 }
151
152 err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
153 inode_unlock(h_inode);
154 if (unlikely(err))
155 goto out_opq;
156
157 if (au_ftest_cpdown(*flags, WHED)) {
158 err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
159 if (unlikely(err))
160 goto out_opq;
161 }
162
163 inode = d_inode(dentry);
164 if (au_ibbot(inode) < bdst)
165 au_set_ibbot(inode, bdst);
166 au_set_h_iptr(inode, bdst, au_igrab(h_inode),
167 au_hi_flags(inode, /*isdir*/1));
168 au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
169 goto out; /* success */
170
171 /* revert */
172 out_opq:
173 if (au_ftest_cpdown(*flags, DIROPQ)) {
174 inode_lock_nested(h_inode, AuLsc_I_CHILD);
175 rerr = au_diropq_remove(dentry, bdst);
176 inode_unlock(h_inode);
177 if (unlikely(rerr)) {
178 AuIOErr("failed removing diropq for %pd b%d (%d)\n",
179 dentry, bdst, rerr);
180 err = -EIO;
181 goto out;
182 }
183 }
184 out_dir:
185 if (au_ftest_cpdown(*flags, MADE_DIR)) {
186 rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
187 if (unlikely(rerr)) {
188 AuIOErr("failed removing %pd b%d (%d)\n",
189 dentry, bdst, rerr);
190 err = -EIO;
191 }
192 }
193 out_put:
194 au_set_h_dptr(dentry, bdst, NULL);
195 if (au_dbbot(dentry) == bdst)
196 au_update_dbbot(dentry);
197 out:
198 dput(parent);
199 return err;
200 }
201
202 int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
203 {
204 int err;
205 unsigned int flags;
206
207 flags = 0;
208 err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
209
210 return err;
211 }
212
213 /* ---------------------------------------------------------------------- */
214
215 /* policies for create */
216
217 int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
218 {
219 int err, i, j, ndentry;
220 aufs_bindex_t bopq;
221 struct au_dcsub_pages dpages;
222 struct au_dpage *dpage;
223 struct dentry **dentries, *parent, *d;
224
225 err = au_dpages_init(&dpages, GFP_NOFS);
226 if (unlikely(err))
227 goto out;
228 parent = dget_parent(dentry);
229 err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
230 if (unlikely(err))
231 goto out_free;
232
233 err = bindex;
234 for (i = 0; i < dpages.ndpage; i++) {
235 dpage = dpages.dpages + i;
236 dentries = dpage->dentries;
237 ndentry = dpage->ndentry;
238 for (j = 0; j < ndentry; j++) {
239 d = dentries[j];
240 di_read_lock_parent2(d, !AuLock_IR);
241 bopq = au_dbdiropq(d);
242 di_read_unlock(d, !AuLock_IR);
243 if (bopq >= 0 && bopq < err)
244 err = bopq;
245 }
246 }
247
248 out_free:
249 dput(parent);
250 au_dpages_free(&dpages);
251 out:
252 return err;
253 }
254
255 static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
256 {
257 for (; bindex >= 0; bindex--)
258 if (!au_br_rdonly(au_sbr(sb, bindex)))
259 return bindex;
260 return -EROFS;
261 }
262
263 /* top down parent */
264 static int au_wbr_create_tdp(struct dentry *dentry,
265 unsigned int flags __maybe_unused)
266 {
267 int err;
268 aufs_bindex_t btop, bindex;
269 struct super_block *sb;
270 struct dentry *parent, *h_parent;
271
272 sb = dentry->d_sb;
273 btop = au_dbtop(dentry);
274 err = btop;
275 if (!au_br_rdonly(au_sbr(sb, btop)))
276 goto out;
277
278 err = -EROFS;
279 parent = dget_parent(dentry);
280 for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
281 h_parent = au_h_dptr(parent, bindex);
282 if (!h_parent || d_is_negative(h_parent))
283 continue;
284
285 if (!au_br_rdonly(au_sbr(sb, bindex))) {
286 err = bindex;
287 break;
288 }
289 }
290 dput(parent);
291
292 /* bottom up here */
293 if (unlikely(err < 0)) {
294 err = au_wbr_bu(sb, btop - 1);
295 if (err >= 0)
296 err = au_wbr_nonopq(dentry, err);
297 }
298
299 out:
300 AuDbg("b%d\n", err);
301 return err;
302 }
303
304 /* ---------------------------------------------------------------------- */
305
306 /* an exception for the policy other than tdp */
307 static int au_wbr_create_exp(struct dentry *dentry)
308 {
309 int err;
310 aufs_bindex_t bwh, bdiropq;
311 struct dentry *parent;
312
313 err = -1;
314 bwh = au_dbwh(dentry);
315 parent = dget_parent(dentry);
316 bdiropq = au_dbdiropq(parent);
317 if (bwh >= 0) {
318 if (bdiropq >= 0)
319 err = min(bdiropq, bwh);
320 else
321 err = bwh;
322 AuDbg("%d\n", err);
323 } else if (bdiropq >= 0) {
324 err = bdiropq;
325 AuDbg("%d\n", err);
326 }
327 dput(parent);
328
329 if (err >= 0)
330 err = au_wbr_nonopq(dentry, err);
331
332 if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
333 err = -1;
334
335 AuDbg("%d\n", err);
336 return err;
337 }
338
339 /* ---------------------------------------------------------------------- */
340
341 /* round robin */
342 static int au_wbr_create_init_rr(struct super_block *sb)
343 {
344 int err;
345
346 err = au_wbr_bu(sb, au_sbbot(sb));
347 atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
348 /* smp_mb(); */
349
350 AuDbg("b%d\n", err);
351 return err;
352 }
353
354 static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
355 {
356 int err, nbr;
357 unsigned int u;
358 aufs_bindex_t bindex, bbot;
359 struct super_block *sb;
360 atomic_t *next;
361
362 err = au_wbr_create_exp(dentry);
363 if (err >= 0)
364 goto out;
365
366 sb = dentry->d_sb;
367 next = &au_sbi(sb)->si_wbr_rr_next;
368 bbot = au_sbbot(sb);
369 nbr = bbot + 1;
370 for (bindex = 0; bindex <= bbot; bindex++) {
371 if (!au_ftest_wbr(flags, DIR)) {
372 err = atomic_dec_return(next) + 1;
373 /* modulo for 0 is meaningless */
374 if (unlikely(!err))
375 err = atomic_dec_return(next) + 1;
376 } else
377 err = atomic_read(next);
378 AuDbg("%d\n", err);
379 u = err;
380 err = u % nbr;
381 AuDbg("%d\n", err);
382 if (!au_br_rdonly(au_sbr(sb, err)))
383 break;
384 err = -EROFS;
385 }
386
387 if (err >= 0)
388 err = au_wbr_nonopq(dentry, err);
389
390 out:
391 AuDbg("%d\n", err);
392 return err;
393 }
394
395 /* ---------------------------------------------------------------------- */
396
397 /* most free space */
398 static void au_mfs(struct dentry *dentry, struct dentry *parent)
399 {
400 struct super_block *sb;
401 struct au_branch *br;
402 struct au_wbr_mfs *mfs;
403 struct dentry *h_parent;
404 aufs_bindex_t bindex, bbot;
405 int err;
406 unsigned long long b, bavail;
407 struct path h_path;
408 /* reduce the stack usage */
409 struct kstatfs *st;
410
411 st = kmalloc(sizeof(*st), GFP_NOFS);
412 if (unlikely(!st)) {
413 AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
414 return;
415 }
416
417 bavail = 0;
418 sb = dentry->d_sb;
419 mfs = &au_sbi(sb)->si_wbr_mfs;
420 MtxMustLock(&mfs->mfs_lock);
421 mfs->mfs_bindex = -EROFS;
422 mfs->mfsrr_bytes = 0;
423 if (!parent) {
424 bindex = 0;
425 bbot = au_sbbot(sb);
426 } else {
427 bindex = au_dbtop(parent);
428 bbot = au_dbtaildir(parent);
429 }
430
431 for (; bindex <= bbot; bindex++) {
432 if (parent) {
433 h_parent = au_h_dptr(parent, bindex);
434 if (!h_parent || d_is_negative(h_parent))
435 continue;
436 }
437 br = au_sbr(sb, bindex);
438 if (au_br_rdonly(br))
439 continue;
440
441 /* sb->s_root for NFS is unreliable */
442 h_path.mnt = au_br_mnt(br);
443 h_path.dentry = h_path.mnt->mnt_root;
444 err = vfs_statfs(&h_path, st);
445 if (unlikely(err)) {
446 AuWarn1("failed statfs, b%d, %d\n", bindex, err);
447 continue;
448 }
449
450 /* when the available size is equal, select the lower one */
451 BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
452 || sizeof(b) < sizeof(st->f_bsize));
453 b = st->f_bavail * st->f_bsize;
454 br->br_wbr->wbr_bytes = b;
455 if (b >= bavail) {
456 bavail = b;
457 mfs->mfs_bindex = bindex;
458 mfs->mfs_jiffy = jiffies;
459 }
460 }
461
462 mfs->mfsrr_bytes = bavail;
463 AuDbg("b%d\n", mfs->mfs_bindex);
464 kfree(st);
465 }
466
467 static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
468 {
469 int err;
470 struct dentry *parent;
471 struct super_block *sb;
472 struct au_wbr_mfs *mfs;
473
474 err = au_wbr_create_exp(dentry);
475 if (err >= 0)
476 goto out;
477
478 sb = dentry->d_sb;
479 parent = NULL;
480 if (au_ftest_wbr(flags, PARENT))
481 parent = dget_parent(dentry);
482 mfs = &au_sbi(sb)->si_wbr_mfs;
483 mutex_lock(&mfs->mfs_lock);
484 if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
485 || mfs->mfs_bindex < 0
486 || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
487 au_mfs(dentry, parent);
488 mutex_unlock(&mfs->mfs_lock);
489 err = mfs->mfs_bindex;
490 dput(parent);
491
492 if (err >= 0)
493 err = au_wbr_nonopq(dentry, err);
494
495 out:
496 AuDbg("b%d\n", err);
497 return err;
498 }
499
500 static int au_wbr_create_init_mfs(struct super_block *sb)
501 {
502 struct au_wbr_mfs *mfs;
503
504 mfs = &au_sbi(sb)->si_wbr_mfs;
505 mutex_init(&mfs->mfs_lock);
506 mfs->mfs_jiffy = 0;
507 mfs->mfs_bindex = -EROFS;
508
509 return 0;
510 }
511
512 static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
513 {
514 mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
515 return 0;
516 }
517
518 /* ---------------------------------------------------------------------- */
519
520 /* top down regardless parent, and then mfs */
521 static int au_wbr_create_tdmfs(struct dentry *dentry,
522 unsigned int flags __maybe_unused)
523 {
524 int err;
525 aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
526 unsigned long long watermark;
527 struct super_block *sb;
528 struct au_wbr_mfs *mfs;
529 struct au_branch *br;
530 struct dentry *parent;
531
532 sb = dentry->d_sb;
533 mfs = &au_sbi(sb)->si_wbr_mfs;
534 mutex_lock(&mfs->mfs_lock);
535 if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
536 || mfs->mfs_bindex < 0)
537 au_mfs(dentry, /*parent*/NULL);
538 watermark = mfs->mfsrr_watermark;
539 bmfs = mfs->mfs_bindex;
540 mutex_unlock(&mfs->mfs_lock);
541
542 /* another style of au_wbr_create_exp() */
543 bwh = au_dbwh(dentry);
544 parent = dget_parent(dentry);
545 btail = au_dbtaildir(parent);
546 if (bwh >= 0 && bwh < btail)
547 btail = bwh;
548
549 err = au_wbr_nonopq(dentry, btail);
550 if (unlikely(err < 0))
551 goto out;
552 btail = err;
553 bfound = -1;
554 for (bindex = 0; bindex <= btail; bindex++) {
555 br = au_sbr(sb, bindex);
556 if (au_br_rdonly(br))
557 continue;
558 if (br->br_wbr->wbr_bytes > watermark) {
559 bfound = bindex;
560 break;
561 }
562 }
563 err = bfound;
564 if (err < 0)
565 err = bmfs;
566
567 out:
568 dput(parent);
569 AuDbg("b%d\n", err);
570 return err;
571 }
572
573 /* ---------------------------------------------------------------------- */
574
575 /* most free space and then round robin */
576 static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
577 {
578 int err;
579 struct au_wbr_mfs *mfs;
580
581 err = au_wbr_create_mfs(dentry, flags);
582 if (err >= 0) {
583 mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
584 mutex_lock(&mfs->mfs_lock);
585 if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
586 err = au_wbr_create_rr(dentry, flags);
587 mutex_unlock(&mfs->mfs_lock);
588 }
589
590 AuDbg("b%d\n", err);
591 return err;
592 }
593
594 static int au_wbr_create_init_mfsrr(struct super_block *sb)
595 {
596 int err;
597
598 au_wbr_create_init_mfs(sb); /* ignore */
599 err = au_wbr_create_init_rr(sb);
600
601 return err;
602 }
603
604 /* ---------------------------------------------------------------------- */
605
606 /* top down parent and most free space */
607 static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
608 {
609 int err, e2;
610 unsigned long long b;
611 aufs_bindex_t bindex, btop, bbot;
612 struct super_block *sb;
613 struct dentry *parent, *h_parent;
614 struct au_branch *br;
615
616 err = au_wbr_create_tdp(dentry, flags);
617 if (unlikely(err < 0))
618 goto out;
619 parent = dget_parent(dentry);
620 btop = au_dbtop(parent);
621 bbot = au_dbtaildir(parent);
622 if (btop == bbot)
623 goto out_parent; /* success */
624
625 e2 = au_wbr_create_mfs(dentry, flags);
626 if (e2 < 0)
627 goto out_parent; /* success */
628
629 /* when the available size is equal, select upper one */
630 sb = dentry->d_sb;
631 br = au_sbr(sb, err);
632 b = br->br_wbr->wbr_bytes;
633 AuDbg("b%d, %llu\n", err, b);
634
635 for (bindex = btop; bindex <= bbot; bindex++) {
636 h_parent = au_h_dptr(parent, bindex);
637 if (!h_parent || d_is_negative(h_parent))
638 continue;
639
640 br = au_sbr(sb, bindex);
641 if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
642 b = br->br_wbr->wbr_bytes;
643 err = bindex;
644 AuDbg("b%d, %llu\n", err, b);
645 }
646 }
647
648 if (err >= 0)
649 err = au_wbr_nonopq(dentry, err);
650
651 out_parent:
652 dput(parent);
653 out:
654 AuDbg("b%d\n", err);
655 return err;
656 }
657
658 /* ---------------------------------------------------------------------- */
659
660 /*
661 * - top down parent
662 * - most free space with parent
663 * - most free space round-robin regardless parent
664 */
665 static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
666 {
667 int err;
668 unsigned long long watermark;
669 struct super_block *sb;
670 struct au_branch *br;
671 struct au_wbr_mfs *mfs;
672
673 err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
674 if (unlikely(err < 0))
675 goto out;
676
677 sb = dentry->d_sb;
678 br = au_sbr(sb, err);
679 mfs = &au_sbi(sb)->si_wbr_mfs;
680 mutex_lock(&mfs->mfs_lock);
681 watermark = mfs->mfsrr_watermark;
682 mutex_unlock(&mfs->mfs_lock);
683 if (br->br_wbr->wbr_bytes < watermark)
684 /* regardless the parent dir */
685 err = au_wbr_create_mfsrr(dentry, flags);
686
687 out:
688 AuDbg("b%d\n", err);
689 return err;
690 }
691
692 /* ---------------------------------------------------------------------- */
693
694 /* policies for copyup */
695
696 /* top down parent */
697 static int au_wbr_copyup_tdp(struct dentry *dentry)
698 {
699 return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
700 }
701
702 /* bottom up parent */
703 static int au_wbr_copyup_bup(struct dentry *dentry)
704 {
705 int err;
706 aufs_bindex_t bindex, btop;
707 struct dentry *parent, *h_parent;
708 struct super_block *sb;
709
710 err = -EROFS;
711 sb = dentry->d_sb;
712 parent = dget_parent(dentry);
713 btop = au_dbtop(parent);
714 for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
715 h_parent = au_h_dptr(parent, bindex);
716 if (!h_parent || d_is_negative(h_parent))
717 continue;
718
719 if (!au_br_rdonly(au_sbr(sb, bindex))) {
720 err = bindex;
721 break;
722 }
723 }
724 dput(parent);
725
726 /* bottom up here */
727 if (unlikely(err < 0))
728 err = au_wbr_bu(sb, btop - 1);
729
730 AuDbg("b%d\n", err);
731 return err;
732 }
733
734 /* bottom up */
735 int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
736 {
737 int err;
738
739 err = au_wbr_bu(dentry->d_sb, btop);
740 AuDbg("b%d\n", err);
741 if (err > btop)
742 err = au_wbr_nonopq(dentry, err);
743
744 AuDbg("b%d\n", err);
745 return err;
746 }
747
748 static int au_wbr_copyup_bu(struct dentry *dentry)
749 {
750 int err;
751 aufs_bindex_t btop;
752
753 btop = au_dbtop(dentry);
754 err = au_wbr_do_copyup_bu(dentry, btop);
755 return err;
756 }
757
758 /* ---------------------------------------------------------------------- */
759
760 struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
761 [AuWbrCopyup_TDP] = {
762 .copyup = au_wbr_copyup_tdp
763 },
764 [AuWbrCopyup_BUP] = {
765 .copyup = au_wbr_copyup_bup
766 },
767 [AuWbrCopyup_BU] = {
768 .copyup = au_wbr_copyup_bu
769 }
770 };
771
772 struct au_wbr_create_operations au_wbr_create_ops[] = {
773 [AuWbrCreate_TDP] = {
774 .create = au_wbr_create_tdp
775 },
776 [AuWbrCreate_RR] = {
777 .create = au_wbr_create_rr,
778 .init = au_wbr_create_init_rr
779 },
780 [AuWbrCreate_MFS] = {
781 .create = au_wbr_create_mfs,
782 .init = au_wbr_create_init_mfs,
783 .fin = au_wbr_create_fin_mfs
784 },
785 [AuWbrCreate_MFSV] = {
786 .create = au_wbr_create_mfs,
787 .init = au_wbr_create_init_mfs,
788 .fin = au_wbr_create_fin_mfs
789 },
790 [AuWbrCreate_MFSRR] = {
791 .create = au_wbr_create_mfsrr,
792 .init = au_wbr_create_init_mfsrr,
793 .fin = au_wbr_create_fin_mfs
794 },
795 [AuWbrCreate_MFSRRV] = {
796 .create = au_wbr_create_mfsrr,
797 .init = au_wbr_create_init_mfsrr,
798 .fin = au_wbr_create_fin_mfs
799 },
800 [AuWbrCreate_TDMFS] = {
801 .create = au_wbr_create_tdmfs,
802 .init = au_wbr_create_init_mfs,
803 .fin = au_wbr_create_fin_mfs
804 },
805 [AuWbrCreate_TDMFSV] = {
806 .create = au_wbr_create_tdmfs,
807 .init = au_wbr_create_init_mfs,
808 .fin = au_wbr_create_fin_mfs
809 },
810 [AuWbrCreate_PMFS] = {
811 .create = au_wbr_create_pmfs,
812 .init = au_wbr_create_init_mfs,
813 .fin = au_wbr_create_fin_mfs
814 },
815 [AuWbrCreate_PMFSV] = {
816 .create = au_wbr_create_pmfs,
817 .init = au_wbr_create_init_mfs,
818 .fin = au_wbr_create_fin_mfs
819 },
820 [AuWbrCreate_PMFSRR] = {
821 .create = au_wbr_create_pmfsrr,
822 .init = au_wbr_create_init_mfsrr,
823 .fin = au_wbr_create_fin_mfs
824 },
825 [AuWbrCreate_PMFSRRV] = {
826 .create = au_wbr_create_pmfsrr,
827 .init = au_wbr_create_init_mfsrr,
828 .fin = au_wbr_create_fin_mfs
829 }
830 };