.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2011 Novell Inc. |
---|
3 | 4 | * Copyright (C) 2016 Red Hat, Inc. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
7 | | - * the Free Software Foundation. |
---|
8 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | #include <linux/fs.h> |
---|
.. | .. |
---|
21 | 18 | int ovl_want_write(struct dentry *dentry) |
---|
22 | 19 | { |
---|
23 | 20 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |
---|
24 | | - return mnt_want_write(ofs->upper_mnt); |
---|
| 21 | + return mnt_want_write(ovl_upper_mnt(ofs)); |
---|
25 | 22 | } |
---|
26 | 23 | |
---|
27 | 24 | void ovl_drop_write(struct dentry *dentry) |
---|
28 | 25 | { |
---|
29 | 26 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |
---|
30 | | - mnt_drop_write(ofs->upper_mnt); |
---|
| 27 | + mnt_drop_write(ovl_upper_mnt(ofs)); |
---|
31 | 28 | } |
---|
32 | 29 | |
---|
33 | 30 | struct dentry *ovl_workdir(struct dentry *dentry) |
---|
.. | .. |
---|
45 | 42 | return override_creds(ofs->creator_cred); |
---|
46 | 43 | } |
---|
47 | 44 | |
---|
48 | | -void ovl_revert_creds(const struct cred *old_cred) |
---|
| 45 | +void ovl_revert_creds(struct super_block *sb, const struct cred *old_cred) |
---|
49 | 46 | { |
---|
50 | 47 | if (old_cred) |
---|
51 | 48 | revert_creds(old_cred); |
---|
52 | | -} |
---|
53 | | - |
---|
54 | | -ssize_t ovl_vfs_getxattr(struct dentry *dentry, const char *name, void *buf, |
---|
55 | | - size_t size) |
---|
56 | | -{ |
---|
57 | | - return __vfs_getxattr(dentry, d_inode(dentry), name, buf, size); |
---|
58 | | -} |
---|
59 | | - |
---|
60 | | -struct super_block *ovl_same_sb(struct super_block *sb) |
---|
61 | | -{ |
---|
62 | | - struct ovl_fs *ofs = sb->s_fs_info; |
---|
63 | | - |
---|
64 | | - if (!ofs->numlowerfs) |
---|
65 | | - return ofs->upper_mnt->mnt_sb; |
---|
66 | | - else if (ofs->numlowerfs == 1 && !ofs->upper_mnt) |
---|
67 | | - return ofs->lower_fs[0].sb; |
---|
68 | | - else |
---|
69 | | - return NULL; |
---|
70 | 49 | } |
---|
71 | 50 | |
---|
72 | 51 | /* |
---|
.. | .. |
---|
79 | 58 | */ |
---|
80 | 59 | int ovl_can_decode_fh(struct super_block *sb) |
---|
81 | 60 | { |
---|
82 | | - if (!sb->s_export_op || !sb->s_export_op->fh_to_dentry || |
---|
83 | | - uuid_is_null(&sb->s_uuid)) |
---|
| 61 | + if (!sb->s_export_op || !sb->s_export_op->fh_to_dentry) |
---|
84 | 62 | return 0; |
---|
85 | 63 | |
---|
86 | 64 | return sb->s_export_op->encode_fh ? -1 : FILEID_INO32_GEN; |
---|
.. | .. |
---|
120 | 98 | return oe; |
---|
121 | 99 | } |
---|
122 | 100 | |
---|
| 101 | +#define OVL_D_REVALIDATE (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE) |
---|
| 102 | + |
---|
123 | 103 | bool ovl_dentry_remote(struct dentry *dentry) |
---|
124 | 104 | { |
---|
125 | | - return dentry->d_flags & |
---|
126 | | - (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | |
---|
127 | | - DCACHE_OP_REAL); |
---|
| 105 | + return dentry->d_flags & OVL_D_REVALIDATE; |
---|
| 106 | +} |
---|
| 107 | + |
---|
| 108 | +void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry) |
---|
| 109 | +{ |
---|
| 110 | + if (!ovl_dentry_remote(realdentry)) |
---|
| 111 | + return; |
---|
| 112 | + |
---|
| 113 | + spin_lock(&dentry->d_lock); |
---|
| 114 | + dentry->d_flags |= realdentry->d_flags & OVL_D_REVALIDATE; |
---|
| 115 | + spin_unlock(&dentry->d_lock); |
---|
| 116 | +} |
---|
| 117 | + |
---|
| 118 | +void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry) |
---|
| 119 | +{ |
---|
| 120 | + return ovl_dentry_init_flags(dentry, upperdentry, OVL_D_REVALIDATE); |
---|
| 121 | +} |
---|
| 122 | + |
---|
| 123 | +void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry, |
---|
| 124 | + unsigned int mask) |
---|
| 125 | +{ |
---|
| 126 | + struct ovl_entry *oe = OVL_E(dentry); |
---|
| 127 | + unsigned int i, flags = 0; |
---|
| 128 | + |
---|
| 129 | + if (upperdentry) |
---|
| 130 | + flags |= upperdentry->d_flags; |
---|
| 131 | + for (i = 0; i < oe->numlower; i++) |
---|
| 132 | + flags |= oe->lowerstack[i].dentry->d_flags; |
---|
| 133 | + |
---|
| 134 | + spin_lock(&dentry->d_lock); |
---|
| 135 | + dentry->d_flags &= ~mask; |
---|
| 136 | + dentry->d_flags |= flags & mask; |
---|
| 137 | + spin_unlock(&dentry->d_lock); |
---|
128 | 138 | } |
---|
129 | 139 | |
---|
130 | 140 | bool ovl_dentry_weird(struct dentry *dentry) |
---|
.. | .. |
---|
164 | 174 | { |
---|
165 | 175 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |
---|
166 | 176 | |
---|
167 | | - path->mnt = ofs->upper_mnt; |
---|
| 177 | + path->mnt = ovl_upper_mnt(ofs); |
---|
168 | 178 | path->dentry = ovl_dentry_upper(dentry); |
---|
169 | 179 | } |
---|
170 | 180 | |
---|
.. | .. |
---|
216 | 226 | return oe->numlower ? oe->lowerstack[0].dentry : NULL; |
---|
217 | 227 | } |
---|
218 | 228 | |
---|
219 | | -struct ovl_layer *ovl_layer_lower(struct dentry *dentry) |
---|
| 229 | +const struct ovl_layer *ovl_layer_lower(struct dentry *dentry) |
---|
220 | 230 | { |
---|
221 | 231 | struct ovl_entry *oe = dentry->d_fsdata; |
---|
222 | 232 | |
---|
.. | .. |
---|
416 | 426 | oi->redirect = redirect; |
---|
417 | 427 | } |
---|
418 | 428 | |
---|
419 | | -void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, |
---|
420 | | - struct dentry *lowerdentry, struct dentry *lowerdata) |
---|
421 | | -{ |
---|
422 | | - struct inode *realinode = d_inode(upperdentry ?: lowerdentry); |
---|
423 | | - |
---|
424 | | - if (upperdentry) |
---|
425 | | - OVL_I(inode)->__upperdentry = upperdentry; |
---|
426 | | - if (lowerdentry) |
---|
427 | | - OVL_I(inode)->lower = igrab(d_inode(lowerdentry)); |
---|
428 | | - if (lowerdata) |
---|
429 | | - OVL_I(inode)->lowerdata = igrab(d_inode(lowerdata)); |
---|
430 | | - |
---|
431 | | - ovl_copyattr(realinode, inode); |
---|
432 | | - ovl_copyflags(realinode, inode); |
---|
433 | | - if (!inode->i_ino) |
---|
434 | | - inode->i_ino = realinode->i_ino; |
---|
435 | | -} |
---|
436 | | - |
---|
437 | 429 | void ovl_inode_update(struct inode *inode, struct dentry *upperdentry) |
---|
438 | 430 | { |
---|
439 | 431 | struct inode *upperinode = d_inode(upperdentry); |
---|
.. | .. |
---|
446 | 438 | smp_wmb(); |
---|
447 | 439 | OVL_I(inode)->__upperdentry = upperdentry; |
---|
448 | 440 | if (inode_unhashed(inode)) { |
---|
449 | | - if (!inode->i_ino) |
---|
450 | | - inode->i_ino = upperinode->i_ino; |
---|
451 | 441 | inode->i_private = upperinode; |
---|
452 | 442 | __insert_inode_hash(inode, (unsigned long) upperinode); |
---|
453 | 443 | } |
---|
454 | 444 | } |
---|
455 | 445 | |
---|
456 | | -static void ovl_dentry_version_inc(struct dentry *dentry, bool impurity) |
---|
| 446 | +static void ovl_dir_version_inc(struct dentry *dentry, bool impurity) |
---|
457 | 447 | { |
---|
458 | 448 | struct inode *inode = d_inode(dentry); |
---|
459 | 449 | |
---|
460 | 450 | WARN_ON(!inode_is_locked(inode)); |
---|
| 451 | + WARN_ON(!d_is_dir(dentry)); |
---|
461 | 452 | /* |
---|
462 | | - * Version is used by readdir code to keep cache consistent. For merge |
---|
463 | | - * dirs all changes need to be noted. For non-merge dirs, cache only |
---|
464 | | - * contains impure (ones which have been copied up and have origins) |
---|
465 | | - * entries, so only need to note changes to impure entries. |
---|
| 453 | + * Version is used by readdir code to keep cache consistent. |
---|
| 454 | + * For merge dirs (or dirs with origin) all changes need to be noted. |
---|
| 455 | + * For non-merge dirs, cache contains only impure entries (i.e. ones |
---|
| 456 | + * which have been copied up and have origins), so only need to note |
---|
| 457 | + * changes to impure entries. |
---|
466 | 458 | */ |
---|
467 | | - if (OVL_TYPE_MERGE(ovl_path_type(dentry)) || impurity) |
---|
| 459 | + if (!ovl_dir_is_real(dentry) || impurity) |
---|
468 | 460 | OVL_I(inode)->version++; |
---|
469 | 461 | } |
---|
470 | 462 | |
---|
.. | .. |
---|
473 | 465 | /* Copy mtime/ctime */ |
---|
474 | 466 | ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry)); |
---|
475 | 467 | |
---|
476 | | - ovl_dentry_version_inc(dentry, impurity); |
---|
| 468 | + ovl_dir_version_inc(dentry, impurity); |
---|
477 | 469 | } |
---|
478 | 470 | |
---|
479 | 471 | u64 ovl_dentry_version_get(struct dentry *dentry) |
---|
.. | .. |
---|
493 | 485 | |
---|
494 | 486 | struct file *ovl_path_open(struct path *path, int flags) |
---|
495 | 487 | { |
---|
496 | | - return dentry_open(path, flags | O_NOATIME, current_cred()); |
---|
| 488 | + struct inode *inode = d_inode(path->dentry); |
---|
| 489 | + int err, acc_mode; |
---|
| 490 | + |
---|
| 491 | + if (flags & ~(O_ACCMODE | O_LARGEFILE)) |
---|
| 492 | + BUG(); |
---|
| 493 | + |
---|
| 494 | + switch (flags & O_ACCMODE) { |
---|
| 495 | + case O_RDONLY: |
---|
| 496 | + acc_mode = MAY_READ; |
---|
| 497 | + break; |
---|
| 498 | + case O_WRONLY: |
---|
| 499 | + acc_mode = MAY_WRITE; |
---|
| 500 | + break; |
---|
| 501 | + default: |
---|
| 502 | + BUG(); |
---|
| 503 | + } |
---|
| 504 | + |
---|
| 505 | + err = inode_permission(inode, acc_mode | MAY_OPEN); |
---|
| 506 | + if (err) |
---|
| 507 | + return ERR_PTR(err); |
---|
| 508 | + |
---|
| 509 | + /* O_NOATIME is an optimization, don't fail if not permitted */ |
---|
| 510 | + if (inode_owner_or_capable(inode)) |
---|
| 511 | + flags |= O_NOATIME; |
---|
| 512 | + |
---|
| 513 | + return dentry_open(path, flags, current_cred()); |
---|
497 | 514 | } |
---|
498 | 515 | |
---|
499 | 516 | /* Caller should hold ovl_inode->lock */ |
---|
.. | .. |
---|
536 | 553 | |
---|
537 | 554 | int ovl_copy_up_start(struct dentry *dentry, int flags) |
---|
538 | 555 | { |
---|
539 | | - struct ovl_inode *oi = OVL_I(d_inode(dentry)); |
---|
| 556 | + struct inode *inode = d_inode(dentry); |
---|
540 | 557 | int err; |
---|
541 | 558 | |
---|
542 | | - err = mutex_lock_interruptible(&oi->lock); |
---|
| 559 | + err = ovl_inode_lock_interruptible(inode); |
---|
543 | 560 | if (!err && ovl_already_copied_up_locked(dentry, flags)) { |
---|
544 | 561 | err = 1; /* Already copied up */ |
---|
545 | | - mutex_unlock(&oi->lock); |
---|
| 562 | + ovl_inode_unlock(inode); |
---|
546 | 563 | } |
---|
547 | 564 | |
---|
548 | 565 | return err; |
---|
.. | .. |
---|
550 | 567 | |
---|
551 | 568 | void ovl_copy_up_end(struct dentry *dentry) |
---|
552 | 569 | { |
---|
553 | | - mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
---|
| 570 | + ovl_inode_unlock(d_inode(dentry)); |
---|
554 | 571 | } |
---|
555 | 572 | |
---|
556 | | -bool ovl_check_origin_xattr(struct dentry *dentry) |
---|
| 573 | +bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) |
---|
557 | 574 | { |
---|
558 | 575 | ssize_t res; |
---|
559 | 576 | |
---|
560 | | - res = ovl_vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); |
---|
| 577 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); |
---|
561 | 578 | |
---|
562 | 579 | /* Zero size value means "copied up but origin unknown" */ |
---|
563 | 580 | if (res >= 0) |
---|
.. | .. |
---|
566 | 583 | return false; |
---|
567 | 584 | } |
---|
568 | 585 | |
---|
569 | | -bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) |
---|
| 586 | +bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, |
---|
| 587 | + enum ovl_xattr ox) |
---|
570 | 588 | { |
---|
571 | 589 | ssize_t res; |
---|
572 | 590 | char val; |
---|
.. | .. |
---|
574 | 592 | if (!d_is_dir(dentry)) |
---|
575 | 593 | return false; |
---|
576 | 594 | |
---|
577 | | - res = ovl_vfs_getxattr(dentry, name, &val, 1); |
---|
| 595 | + res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1); |
---|
578 | 596 | if (res == 1 && val == 'y') |
---|
579 | 597 | return true; |
---|
580 | 598 | |
---|
581 | 599 | return false; |
---|
582 | 600 | } |
---|
583 | 601 | |
---|
| 602 | +#define OVL_XATTR_OPAQUE_POSTFIX "opaque" |
---|
| 603 | +#define OVL_XATTR_REDIRECT_POSTFIX "redirect" |
---|
| 604 | +#define OVL_XATTR_ORIGIN_POSTFIX "origin" |
---|
| 605 | +#define OVL_XATTR_IMPURE_POSTFIX "impure" |
---|
| 606 | +#define OVL_XATTR_NLINK_POSTFIX "nlink" |
---|
| 607 | +#define OVL_XATTR_UPPER_POSTFIX "upper" |
---|
| 608 | +#define OVL_XATTR_METACOPY_POSTFIX "metacopy" |
---|
| 609 | + |
---|
| 610 | +#define OVL_XATTR_TAB_ENTRY(x) \ |
---|
| 611 | + [x] = OVL_XATTR_PREFIX x ## _POSTFIX |
---|
| 612 | + |
---|
| 613 | +const char *ovl_xattr_table[] = { |
---|
| 614 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_OPAQUE), |
---|
| 615 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_REDIRECT), |
---|
| 616 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_ORIGIN), |
---|
| 617 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE), |
---|
| 618 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK), |
---|
| 619 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER), |
---|
| 620 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY), |
---|
| 621 | +}; |
---|
| 622 | + |
---|
584 | 623 | int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, |
---|
585 | | - const char *name, const void *value, size_t size, |
---|
| 624 | + enum ovl_xattr ox, const void *value, size_t size, |
---|
586 | 625 | int xerr) |
---|
587 | 626 | { |
---|
588 | 627 | int err; |
---|
.. | .. |
---|
591 | 630 | if (ofs->noxattr) |
---|
592 | 631 | return xerr; |
---|
593 | 632 | |
---|
594 | | - err = ovl_do_setxattr(upperdentry, name, value, size, 0); |
---|
| 633 | + err = ovl_do_setxattr(ofs, upperdentry, ox, value, size); |
---|
595 | 634 | |
---|
596 | 635 | if (err == -EOPNOTSUPP) { |
---|
597 | | - pr_warn("overlayfs: cannot set %s xattr on upper\n", name); |
---|
| 636 | + pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox)); |
---|
598 | 637 | ofs->noxattr = true; |
---|
599 | 638 | return xerr; |
---|
600 | 639 | } |
---|
.. | .. |
---|
619 | 658 | ovl_set_flag(OVL_IMPURE, d_inode(dentry)); |
---|
620 | 659 | |
---|
621 | 660 | return err; |
---|
622 | | -} |
---|
623 | | - |
---|
624 | | -void ovl_set_flag(unsigned long flag, struct inode *inode) |
---|
625 | | -{ |
---|
626 | | - set_bit(flag, &OVL_I(inode)->flags); |
---|
627 | | -} |
---|
628 | | - |
---|
629 | | -void ovl_clear_flag(unsigned long flag, struct inode *inode) |
---|
630 | | -{ |
---|
631 | | - clear_bit(flag, &OVL_I(inode)->flags); |
---|
632 | | -} |
---|
633 | | - |
---|
634 | | -bool ovl_test_flag(unsigned long flag, struct inode *inode) |
---|
635 | | -{ |
---|
636 | | - return test_bit(flag, &OVL_I(inode)->flags); |
---|
637 | 661 | } |
---|
638 | 662 | |
---|
639 | 663 | /** |
---|
.. | .. |
---|
718 | 742 | |
---|
719 | 743 | inode = d_inode(upperdentry); |
---|
720 | 744 | if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { |
---|
721 | | - pr_warn_ratelimited("overlayfs: cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", |
---|
| 745 | + pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", |
---|
722 | 746 | upperdentry, inode->i_ino, inode->i_nlink); |
---|
723 | 747 | /* |
---|
724 | 748 | * We either have a bug with persistent union nlink or a lower |
---|
.. | .. |
---|
741 | 765 | index = NULL; |
---|
742 | 766 | } else if (ovl_index_all(dentry->d_sb)) { |
---|
743 | 767 | /* Whiteout orphan index to block future open by handle */ |
---|
744 | | - err = ovl_cleanup_and_whiteout(indexdir, dir, index); |
---|
| 768 | + err = ovl_cleanup_and_whiteout(OVL_FS(dentry->d_sb), |
---|
| 769 | + dir, index); |
---|
745 | 770 | } else { |
---|
746 | 771 | /* Cleanup orphan index entries */ |
---|
747 | 772 | err = ovl_cleanup(dir, index); |
---|
.. | .. |
---|
757 | 782 | return; |
---|
758 | 783 | |
---|
759 | 784 | fail: |
---|
760 | | - pr_err("overlayfs: cleanup index of '%pd2' failed (%i)\n", dentry, err); |
---|
| 785 | + pr_err("cleanup index of '%pd2' failed (%i)\n", dentry, err); |
---|
761 | 786 | goto out; |
---|
762 | 787 | } |
---|
763 | 788 | |
---|
.. | .. |
---|
765 | 790 | * Operations that change overlay inode and upper inode nlink need to be |
---|
766 | 791 | * synchronized with copy up for persistent nlink accounting. |
---|
767 | 792 | */ |
---|
768 | | -int ovl_nlink_start(struct dentry *dentry, bool *locked) |
---|
| 793 | +int ovl_nlink_start(struct dentry *dentry) |
---|
769 | 794 | { |
---|
770 | | - struct ovl_inode *oi = OVL_I(d_inode(dentry)); |
---|
| 795 | + struct inode *inode = d_inode(dentry); |
---|
771 | 796 | const struct cred *old_cred; |
---|
772 | 797 | int err; |
---|
773 | 798 | |
---|
774 | | - if (!d_inode(dentry)) |
---|
775 | | - return 0; |
---|
| 799 | + if (WARN_ON(!inode)) |
---|
| 800 | + return -ENOENT; |
---|
776 | 801 | |
---|
777 | 802 | /* |
---|
778 | 803 | * With inodes index is enabled, we store the union overlay nlink |
---|
.. | .. |
---|
794 | 819 | return err; |
---|
795 | 820 | } |
---|
796 | 821 | |
---|
797 | | - err = mutex_lock_interruptible(&oi->lock); |
---|
| 822 | + err = ovl_inode_lock_interruptible(inode); |
---|
798 | 823 | if (err) |
---|
799 | 824 | return err; |
---|
800 | 825 | |
---|
801 | | - if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, d_inode(dentry))) |
---|
| 826 | + if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, inode)) |
---|
802 | 827 | goto out; |
---|
803 | 828 | |
---|
804 | 829 | old_cred = ovl_override_creds(dentry->d_sb); |
---|
.. | .. |
---|
809 | 834 | * value relative to the upper inode nlink in an upper inode xattr. |
---|
810 | 835 | */ |
---|
811 | 836 | err = ovl_set_nlink_upper(dentry); |
---|
812 | | - ovl_revert_creds(old_cred); |
---|
| 837 | + ovl_revert_creds(dentry->d_sb, old_cred); |
---|
813 | 838 | |
---|
814 | 839 | out: |
---|
815 | 840 | if (err) |
---|
816 | | - mutex_unlock(&oi->lock); |
---|
817 | | - else |
---|
818 | | - *locked = true; |
---|
| 841 | + ovl_inode_unlock(inode); |
---|
819 | 842 | |
---|
820 | 843 | return err; |
---|
821 | 844 | } |
---|
822 | 845 | |
---|
823 | | -void ovl_nlink_end(struct dentry *dentry, bool locked) |
---|
| 846 | +void ovl_nlink_end(struct dentry *dentry) |
---|
824 | 847 | { |
---|
825 | | - if (locked) { |
---|
826 | | - if (ovl_test_flag(OVL_INDEX, d_inode(dentry)) && |
---|
827 | | - d_inode(dentry)->i_nlink == 0) { |
---|
828 | | - const struct cred *old_cred; |
---|
| 848 | + struct inode *inode = d_inode(dentry); |
---|
829 | 849 | |
---|
830 | | - old_cred = ovl_override_creds(dentry->d_sb); |
---|
831 | | - ovl_cleanup_index(dentry); |
---|
832 | | - ovl_revert_creds(old_cred); |
---|
833 | | - } |
---|
| 850 | + if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { |
---|
| 851 | + const struct cred *old_cred; |
---|
834 | 852 | |
---|
835 | | - mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
---|
| 853 | + old_cred = ovl_override_creds(dentry->d_sb); |
---|
| 854 | + ovl_cleanup_index(dentry); |
---|
| 855 | + ovl_revert_creds(dentry->d_sb, old_cred); |
---|
836 | 856 | } |
---|
| 857 | + |
---|
| 858 | + ovl_inode_unlock(inode); |
---|
837 | 859 | } |
---|
838 | 860 | |
---|
839 | 861 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) |
---|
.. | .. |
---|
851 | 873 | err_unlock: |
---|
852 | 874 | unlock_rename(workdir, upperdir); |
---|
853 | 875 | err: |
---|
854 | | - pr_err("overlayfs: failed to lock workdir+upperdir\n"); |
---|
| 876 | + pr_err("failed to lock workdir+upperdir\n"); |
---|
855 | 877 | return -EIO; |
---|
856 | 878 | } |
---|
857 | 879 | |
---|
858 | 880 | /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ |
---|
859 | | -int ovl_check_metacopy_xattr(struct dentry *dentry) |
---|
| 881 | +int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry) |
---|
860 | 882 | { |
---|
861 | 883 | ssize_t res; |
---|
862 | 884 | |
---|
.. | .. |
---|
864 | 886 | if (!S_ISREG(d_inode(dentry)->i_mode)) |
---|
865 | 887 | return 0; |
---|
866 | 888 | |
---|
867 | | - res = ovl_vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); |
---|
| 889 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); |
---|
868 | 890 | if (res < 0) { |
---|
869 | 891 | if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
870 | 892 | return 0; |
---|
.. | .. |
---|
873 | 895 | |
---|
874 | 896 | return 1; |
---|
875 | 897 | out: |
---|
876 | | - pr_warn_ratelimited("overlayfs: failed to get metacopy (%zi)\n", res); |
---|
| 898 | + pr_warn_ratelimited("failed to get metacopy (%zi)\n", res); |
---|
877 | 899 | return res; |
---|
878 | 900 | } |
---|
879 | 901 | |
---|
.. | .. |
---|
893 | 915 | return (oe->numlower > 1); |
---|
894 | 916 | } |
---|
895 | 917 | |
---|
896 | | -ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value, |
---|
897 | | - size_t padding) |
---|
898 | | -{ |
---|
899 | | - ssize_t res; |
---|
900 | | - char *buf = NULL; |
---|
901 | | - |
---|
902 | | - res = ovl_vfs_getxattr(dentry, name, NULL, 0); |
---|
903 | | - if (res < 0) { |
---|
904 | | - if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
905 | | - return -ENODATA; |
---|
906 | | - goto fail; |
---|
907 | | - } |
---|
908 | | - |
---|
909 | | - if (res != 0) { |
---|
910 | | - buf = kzalloc(res + padding, GFP_KERNEL); |
---|
911 | | - if (!buf) |
---|
912 | | - return -ENOMEM; |
---|
913 | | - |
---|
914 | | - res = ovl_vfs_getxattr(dentry, name, buf, res); |
---|
915 | | - if (res < 0) |
---|
916 | | - goto fail; |
---|
917 | | - } |
---|
918 | | - *value = buf; |
---|
919 | | - |
---|
920 | | - return res; |
---|
921 | | - |
---|
922 | | -fail: |
---|
923 | | - pr_warn_ratelimited("overlayfs: failed to get xattr %s: err=%zi)\n", |
---|
924 | | - name, res); |
---|
925 | | - kfree(buf); |
---|
926 | | - return res; |
---|
927 | | -} |
---|
928 | | - |
---|
929 | | -char *ovl_get_redirect_xattr(struct dentry *dentry, int padding) |
---|
| 918 | +char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, |
---|
| 919 | + int padding) |
---|
930 | 920 | { |
---|
931 | 921 | int res; |
---|
932 | 922 | char *s, *next, *buf = NULL; |
---|
933 | 923 | |
---|
934 | | - res = ovl_getxattr(dentry, OVL_XATTR_REDIRECT, &buf, padding + 1); |
---|
935 | | - if (res == -ENODATA) |
---|
| 924 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); |
---|
| 925 | + if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
936 | 926 | return NULL; |
---|
937 | 927 | if (res < 0) |
---|
938 | | - return ERR_PTR(res); |
---|
| 928 | + goto fail; |
---|
| 929 | + if (res == 0) |
---|
| 930 | + goto invalid; |
---|
| 931 | + |
---|
| 932 | + buf = kzalloc(res + padding + 1, GFP_KERNEL); |
---|
| 933 | + if (!buf) |
---|
| 934 | + return ERR_PTR(-ENOMEM); |
---|
| 935 | + |
---|
| 936 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); |
---|
| 937 | + if (res < 0) |
---|
| 938 | + goto fail; |
---|
939 | 939 | if (res == 0) |
---|
940 | 940 | goto invalid; |
---|
941 | 941 | |
---|
.. | .. |
---|
952 | 952 | |
---|
953 | 953 | return buf; |
---|
954 | 954 | invalid: |
---|
955 | | - pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); |
---|
| 955 | + pr_warn_ratelimited("invalid redirect (%s)\n", buf); |
---|
956 | 956 | res = -EINVAL; |
---|
| 957 | + goto err_free; |
---|
| 958 | +fail: |
---|
| 959 | + pr_warn_ratelimited("failed to get redirect (%i)\n", res); |
---|
| 960 | +err_free: |
---|
957 | 961 | kfree(buf); |
---|
958 | 962 | return ERR_PTR(res); |
---|
959 | 963 | } |
---|
| 964 | + |
---|
| 965 | +/* |
---|
| 966 | + * ovl_sync_status() - Check fs sync status for volatile mounts |
---|
| 967 | + * |
---|
| 968 | + * Returns 1 if this is not a volatile mount and a real sync is required. |
---|
| 969 | + * |
---|
| 970 | + * Returns 0 if syncing can be skipped because mount is volatile, and no errors |
---|
| 971 | + * have occurred on the upperdir since the mount. |
---|
| 972 | + * |
---|
| 973 | + * Returns -errno if it is a volatile mount, and the error that occurred since |
---|
| 974 | + * the last mount. If the error code changes, it'll return the latest error |
---|
| 975 | + * code. |
---|
| 976 | + */ |
---|
| 977 | + |
---|
| 978 | +int ovl_sync_status(struct ovl_fs *ofs) |
---|
| 979 | +{ |
---|
| 980 | + struct vfsmount *mnt; |
---|
| 981 | + |
---|
| 982 | + if (ovl_should_sync(ofs)) |
---|
| 983 | + return 1; |
---|
| 984 | + |
---|
| 985 | + mnt = ovl_upper_mnt(ofs); |
---|
| 986 | + if (!mnt) |
---|
| 987 | + return 0; |
---|
| 988 | + |
---|
| 989 | + return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq); |
---|
| 990 | +} |
---|