.. | .. |
---|
| 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; |
---|
.. | .. |
---|
123 | 101 | bool ovl_dentry_remote(struct dentry *dentry) |
---|
124 | 102 | { |
---|
125 | 103 | return dentry->d_flags & |
---|
126 | | - (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | |
---|
127 | | - DCACHE_OP_REAL); |
---|
| 104 | + (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE); |
---|
| 105 | +} |
---|
| 106 | + |
---|
| 107 | +void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *upperdentry, |
---|
| 108 | + unsigned int mask) |
---|
| 109 | +{ |
---|
| 110 | + struct ovl_entry *oe = OVL_E(dentry); |
---|
| 111 | + unsigned int i, flags = 0; |
---|
| 112 | + |
---|
| 113 | + if (upperdentry) |
---|
| 114 | + flags |= upperdentry->d_flags; |
---|
| 115 | + for (i = 0; i < oe->numlower; i++) |
---|
| 116 | + flags |= oe->lowerstack[i].dentry->d_flags; |
---|
| 117 | + |
---|
| 118 | + spin_lock(&dentry->d_lock); |
---|
| 119 | + dentry->d_flags &= ~mask; |
---|
| 120 | + dentry->d_flags |= flags & mask; |
---|
| 121 | + spin_unlock(&dentry->d_lock); |
---|
128 | 122 | } |
---|
129 | 123 | |
---|
130 | 124 | bool ovl_dentry_weird(struct dentry *dentry) |
---|
.. | .. |
---|
164 | 158 | { |
---|
165 | 159 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |
---|
166 | 160 | |
---|
167 | | - path->mnt = ofs->upper_mnt; |
---|
| 161 | + path->mnt = ovl_upper_mnt(ofs); |
---|
168 | 162 | path->dentry = ovl_dentry_upper(dentry); |
---|
169 | 163 | } |
---|
170 | 164 | |
---|
.. | .. |
---|
216 | 210 | return oe->numlower ? oe->lowerstack[0].dentry : NULL; |
---|
217 | 211 | } |
---|
218 | 212 | |
---|
219 | | -struct ovl_layer *ovl_layer_lower(struct dentry *dentry) |
---|
| 213 | +const struct ovl_layer *ovl_layer_lower(struct dentry *dentry) |
---|
220 | 214 | { |
---|
221 | 215 | struct ovl_entry *oe = dentry->d_fsdata; |
---|
222 | 216 | |
---|
.. | .. |
---|
416 | 410 | oi->redirect = redirect; |
---|
417 | 411 | } |
---|
418 | 412 | |
---|
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 | 413 | void ovl_inode_update(struct inode *inode, struct dentry *upperdentry) |
---|
438 | 414 | { |
---|
439 | 415 | struct inode *upperinode = d_inode(upperdentry); |
---|
.. | .. |
---|
446 | 422 | smp_wmb(); |
---|
447 | 423 | OVL_I(inode)->__upperdentry = upperdentry; |
---|
448 | 424 | if (inode_unhashed(inode)) { |
---|
449 | | - if (!inode->i_ino) |
---|
450 | | - inode->i_ino = upperinode->i_ino; |
---|
451 | 425 | inode->i_private = upperinode; |
---|
452 | 426 | __insert_inode_hash(inode, (unsigned long) upperinode); |
---|
453 | 427 | } |
---|
454 | 428 | } |
---|
455 | 429 | |
---|
456 | | -static void ovl_dentry_version_inc(struct dentry *dentry, bool impurity) |
---|
| 430 | +static void ovl_dir_version_inc(struct dentry *dentry, bool impurity) |
---|
457 | 431 | { |
---|
458 | 432 | struct inode *inode = d_inode(dentry); |
---|
459 | 433 | |
---|
460 | 434 | WARN_ON(!inode_is_locked(inode)); |
---|
| 435 | + WARN_ON(!d_is_dir(dentry)); |
---|
461 | 436 | /* |
---|
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. |
---|
| 437 | + * Version is used by readdir code to keep cache consistent. |
---|
| 438 | + * For merge dirs (or dirs with origin) all changes need to be noted. |
---|
| 439 | + * For non-merge dirs, cache contains only impure entries (i.e. ones |
---|
| 440 | + * which have been copied up and have origins), so only need to note |
---|
| 441 | + * changes to impure entries. |
---|
466 | 442 | */ |
---|
467 | | - if (OVL_TYPE_MERGE(ovl_path_type(dentry)) || impurity) |
---|
| 443 | + if (!ovl_dir_is_real(dentry) || impurity) |
---|
468 | 444 | OVL_I(inode)->version++; |
---|
469 | 445 | } |
---|
470 | 446 | |
---|
.. | .. |
---|
473 | 449 | /* Copy mtime/ctime */ |
---|
474 | 450 | ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry)); |
---|
475 | 451 | |
---|
476 | | - ovl_dentry_version_inc(dentry, impurity); |
---|
| 452 | + ovl_dir_version_inc(dentry, impurity); |
---|
477 | 453 | } |
---|
478 | 454 | |
---|
479 | 455 | u64 ovl_dentry_version_get(struct dentry *dentry) |
---|
.. | .. |
---|
493 | 469 | |
---|
494 | 470 | struct file *ovl_path_open(struct path *path, int flags) |
---|
495 | 471 | { |
---|
496 | | - return dentry_open(path, flags | O_NOATIME, current_cred()); |
---|
| 472 | + struct inode *inode = d_inode(path->dentry); |
---|
| 473 | + int err, acc_mode; |
---|
| 474 | + |
---|
| 475 | + if (flags & ~(O_ACCMODE | O_LARGEFILE)) |
---|
| 476 | + BUG(); |
---|
| 477 | + |
---|
| 478 | + switch (flags & O_ACCMODE) { |
---|
| 479 | + case O_RDONLY: |
---|
| 480 | + acc_mode = MAY_READ; |
---|
| 481 | + break; |
---|
| 482 | + case O_WRONLY: |
---|
| 483 | + acc_mode = MAY_WRITE; |
---|
| 484 | + break; |
---|
| 485 | + default: |
---|
| 486 | + BUG(); |
---|
| 487 | + } |
---|
| 488 | + |
---|
| 489 | + err = inode_permission(inode, acc_mode | MAY_OPEN); |
---|
| 490 | + if (err) |
---|
| 491 | + return ERR_PTR(err); |
---|
| 492 | + |
---|
| 493 | + /* O_NOATIME is an optimization, don't fail if not permitted */ |
---|
| 494 | + if (inode_owner_or_capable(inode)) |
---|
| 495 | + flags |= O_NOATIME; |
---|
| 496 | + |
---|
| 497 | + return dentry_open(path, flags, current_cred()); |
---|
497 | 498 | } |
---|
498 | 499 | |
---|
499 | 500 | /* Caller should hold ovl_inode->lock */ |
---|
.. | .. |
---|
536 | 537 | |
---|
537 | 538 | int ovl_copy_up_start(struct dentry *dentry, int flags) |
---|
538 | 539 | { |
---|
539 | | - struct ovl_inode *oi = OVL_I(d_inode(dentry)); |
---|
| 540 | + struct inode *inode = d_inode(dentry); |
---|
540 | 541 | int err; |
---|
541 | 542 | |
---|
542 | | - err = mutex_lock_interruptible(&oi->lock); |
---|
| 543 | + err = ovl_inode_lock_interruptible(inode); |
---|
543 | 544 | if (!err && ovl_already_copied_up_locked(dentry, flags)) { |
---|
544 | 545 | err = 1; /* Already copied up */ |
---|
545 | | - mutex_unlock(&oi->lock); |
---|
| 546 | + ovl_inode_unlock(inode); |
---|
546 | 547 | } |
---|
547 | 548 | |
---|
548 | 549 | return err; |
---|
.. | .. |
---|
550 | 551 | |
---|
551 | 552 | void ovl_copy_up_end(struct dentry *dentry) |
---|
552 | 553 | { |
---|
553 | | - mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
---|
| 554 | + ovl_inode_unlock(d_inode(dentry)); |
---|
554 | 555 | } |
---|
555 | 556 | |
---|
556 | | -bool ovl_check_origin_xattr(struct dentry *dentry) |
---|
| 557 | +bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) |
---|
557 | 558 | { |
---|
558 | 559 | ssize_t res; |
---|
559 | 560 | |
---|
560 | | - res = ovl_vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); |
---|
| 561 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); |
---|
561 | 562 | |
---|
562 | 563 | /* Zero size value means "copied up but origin unknown" */ |
---|
563 | 564 | if (res >= 0) |
---|
.. | .. |
---|
566 | 567 | return false; |
---|
567 | 568 | } |
---|
568 | 569 | |
---|
569 | | -bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) |
---|
| 570 | +bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, |
---|
| 571 | + enum ovl_xattr ox) |
---|
570 | 572 | { |
---|
571 | 573 | ssize_t res; |
---|
572 | 574 | char val; |
---|
.. | .. |
---|
574 | 576 | if (!d_is_dir(dentry)) |
---|
575 | 577 | return false; |
---|
576 | 578 | |
---|
577 | | - res = ovl_vfs_getxattr(dentry, name, &val, 1); |
---|
| 579 | + res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1); |
---|
578 | 580 | if (res == 1 && val == 'y') |
---|
579 | 581 | return true; |
---|
580 | 582 | |
---|
581 | 583 | return false; |
---|
582 | 584 | } |
---|
583 | 585 | |
---|
| 586 | +#define OVL_XATTR_OPAQUE_POSTFIX "opaque" |
---|
| 587 | +#define OVL_XATTR_REDIRECT_POSTFIX "redirect" |
---|
| 588 | +#define OVL_XATTR_ORIGIN_POSTFIX "origin" |
---|
| 589 | +#define OVL_XATTR_IMPURE_POSTFIX "impure" |
---|
| 590 | +#define OVL_XATTR_NLINK_POSTFIX "nlink" |
---|
| 591 | +#define OVL_XATTR_UPPER_POSTFIX "upper" |
---|
| 592 | +#define OVL_XATTR_METACOPY_POSTFIX "metacopy" |
---|
| 593 | + |
---|
| 594 | +#define OVL_XATTR_TAB_ENTRY(x) \ |
---|
| 595 | + [x] = OVL_XATTR_PREFIX x ## _POSTFIX |
---|
| 596 | + |
---|
| 597 | +const char *ovl_xattr_table[] = { |
---|
| 598 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_OPAQUE), |
---|
| 599 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_REDIRECT), |
---|
| 600 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_ORIGIN), |
---|
| 601 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE), |
---|
| 602 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK), |
---|
| 603 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER), |
---|
| 604 | + OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY), |
---|
| 605 | +}; |
---|
| 606 | + |
---|
584 | 607 | int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, |
---|
585 | | - const char *name, const void *value, size_t size, |
---|
| 608 | + enum ovl_xattr ox, const void *value, size_t size, |
---|
586 | 609 | int xerr) |
---|
587 | 610 | { |
---|
588 | 611 | int err; |
---|
.. | .. |
---|
591 | 614 | if (ofs->noxattr) |
---|
592 | 615 | return xerr; |
---|
593 | 616 | |
---|
594 | | - err = ovl_do_setxattr(upperdentry, name, value, size, 0); |
---|
| 617 | + err = ovl_do_setxattr(ofs, upperdentry, ox, value, size); |
---|
595 | 618 | |
---|
596 | 619 | if (err == -EOPNOTSUPP) { |
---|
597 | | - pr_warn("overlayfs: cannot set %s xattr on upper\n", name); |
---|
| 620 | + pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox)); |
---|
598 | 621 | ofs->noxattr = true; |
---|
599 | 622 | return xerr; |
---|
600 | 623 | } |
---|
.. | .. |
---|
619 | 642 | ovl_set_flag(OVL_IMPURE, d_inode(dentry)); |
---|
620 | 643 | |
---|
621 | 644 | 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 | 645 | } |
---|
638 | 646 | |
---|
639 | 647 | /** |
---|
.. | .. |
---|
718 | 726 | |
---|
719 | 727 | inode = d_inode(upperdentry); |
---|
720 | 728 | if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { |
---|
721 | | - pr_warn_ratelimited("overlayfs: cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", |
---|
| 729 | + pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", |
---|
722 | 730 | upperdentry, inode->i_ino, inode->i_nlink); |
---|
723 | 731 | /* |
---|
724 | 732 | * We either have a bug with persistent union nlink or a lower |
---|
.. | .. |
---|
741 | 749 | index = NULL; |
---|
742 | 750 | } else if (ovl_index_all(dentry->d_sb)) { |
---|
743 | 751 | /* Whiteout orphan index to block future open by handle */ |
---|
744 | | - err = ovl_cleanup_and_whiteout(indexdir, dir, index); |
---|
| 752 | + err = ovl_cleanup_and_whiteout(OVL_FS(dentry->d_sb), |
---|
| 753 | + dir, index); |
---|
745 | 754 | } else { |
---|
746 | 755 | /* Cleanup orphan index entries */ |
---|
747 | 756 | err = ovl_cleanup(dir, index); |
---|
.. | .. |
---|
757 | 766 | return; |
---|
758 | 767 | |
---|
759 | 768 | fail: |
---|
760 | | - pr_err("overlayfs: cleanup index of '%pd2' failed (%i)\n", dentry, err); |
---|
| 769 | + pr_err("cleanup index of '%pd2' failed (%i)\n", dentry, err); |
---|
761 | 770 | goto out; |
---|
762 | 771 | } |
---|
763 | 772 | |
---|
.. | .. |
---|
765 | 774 | * Operations that change overlay inode and upper inode nlink need to be |
---|
766 | 775 | * synchronized with copy up for persistent nlink accounting. |
---|
767 | 776 | */ |
---|
768 | | -int ovl_nlink_start(struct dentry *dentry, bool *locked) |
---|
| 777 | +int ovl_nlink_start(struct dentry *dentry) |
---|
769 | 778 | { |
---|
770 | | - struct ovl_inode *oi = OVL_I(d_inode(dentry)); |
---|
| 779 | + struct inode *inode = d_inode(dentry); |
---|
771 | 780 | const struct cred *old_cred; |
---|
772 | 781 | int err; |
---|
773 | 782 | |
---|
774 | | - if (!d_inode(dentry)) |
---|
775 | | - return 0; |
---|
| 783 | + if (WARN_ON(!inode)) |
---|
| 784 | + return -ENOENT; |
---|
776 | 785 | |
---|
777 | 786 | /* |
---|
778 | 787 | * With inodes index is enabled, we store the union overlay nlink |
---|
.. | .. |
---|
794 | 803 | return err; |
---|
795 | 804 | } |
---|
796 | 805 | |
---|
797 | | - err = mutex_lock_interruptible(&oi->lock); |
---|
| 806 | + err = ovl_inode_lock_interruptible(inode); |
---|
798 | 807 | if (err) |
---|
799 | 808 | return err; |
---|
800 | 809 | |
---|
801 | | - if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, d_inode(dentry))) |
---|
| 810 | + if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, inode)) |
---|
802 | 811 | goto out; |
---|
803 | 812 | |
---|
804 | 813 | old_cred = ovl_override_creds(dentry->d_sb); |
---|
.. | .. |
---|
809 | 818 | * value relative to the upper inode nlink in an upper inode xattr. |
---|
810 | 819 | */ |
---|
811 | 820 | err = ovl_set_nlink_upper(dentry); |
---|
812 | | - ovl_revert_creds(old_cred); |
---|
| 821 | + ovl_revert_creds(dentry->d_sb, old_cred); |
---|
813 | 822 | |
---|
814 | 823 | out: |
---|
815 | 824 | if (err) |
---|
816 | | - mutex_unlock(&oi->lock); |
---|
817 | | - else |
---|
818 | | - *locked = true; |
---|
| 825 | + ovl_inode_unlock(inode); |
---|
819 | 826 | |
---|
820 | 827 | return err; |
---|
821 | 828 | } |
---|
822 | 829 | |
---|
823 | | -void ovl_nlink_end(struct dentry *dentry, bool locked) |
---|
| 830 | +void ovl_nlink_end(struct dentry *dentry) |
---|
824 | 831 | { |
---|
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; |
---|
| 832 | + struct inode *inode = d_inode(dentry); |
---|
829 | 833 | |
---|
830 | | - old_cred = ovl_override_creds(dentry->d_sb); |
---|
831 | | - ovl_cleanup_index(dentry); |
---|
832 | | - ovl_revert_creds(old_cred); |
---|
833 | | - } |
---|
| 834 | + if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { |
---|
| 835 | + const struct cred *old_cred; |
---|
834 | 836 | |
---|
835 | | - mutex_unlock(&OVL_I(d_inode(dentry))->lock); |
---|
| 837 | + old_cred = ovl_override_creds(dentry->d_sb); |
---|
| 838 | + ovl_cleanup_index(dentry); |
---|
| 839 | + ovl_revert_creds(dentry->d_sb, old_cred); |
---|
836 | 840 | } |
---|
| 841 | + |
---|
| 842 | + ovl_inode_unlock(inode); |
---|
837 | 843 | } |
---|
838 | 844 | |
---|
839 | 845 | int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) |
---|
.. | .. |
---|
851 | 857 | err_unlock: |
---|
852 | 858 | unlock_rename(workdir, upperdir); |
---|
853 | 859 | err: |
---|
854 | | - pr_err("overlayfs: failed to lock workdir+upperdir\n"); |
---|
| 860 | + pr_err("failed to lock workdir+upperdir\n"); |
---|
855 | 861 | return -EIO; |
---|
856 | 862 | } |
---|
857 | 863 | |
---|
858 | 864 | /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ |
---|
859 | | -int ovl_check_metacopy_xattr(struct dentry *dentry) |
---|
| 865 | +int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry) |
---|
860 | 866 | { |
---|
861 | 867 | ssize_t res; |
---|
862 | 868 | |
---|
.. | .. |
---|
864 | 870 | if (!S_ISREG(d_inode(dentry)->i_mode)) |
---|
865 | 871 | return 0; |
---|
866 | 872 | |
---|
867 | | - res = ovl_vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); |
---|
| 873 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); |
---|
868 | 874 | if (res < 0) { |
---|
869 | 875 | if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
870 | 876 | return 0; |
---|
.. | .. |
---|
873 | 879 | |
---|
874 | 880 | return 1; |
---|
875 | 881 | out: |
---|
876 | | - pr_warn_ratelimited("overlayfs: failed to get metacopy (%zi)\n", res); |
---|
| 882 | + pr_warn_ratelimited("failed to get metacopy (%zi)\n", res); |
---|
877 | 883 | return res; |
---|
878 | 884 | } |
---|
879 | 885 | |
---|
.. | .. |
---|
893 | 899 | return (oe->numlower > 1); |
---|
894 | 900 | } |
---|
895 | 901 | |
---|
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) |
---|
| 902 | +char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, |
---|
| 903 | + int padding) |
---|
930 | 904 | { |
---|
931 | 905 | int res; |
---|
932 | 906 | char *s, *next, *buf = NULL; |
---|
933 | 907 | |
---|
934 | | - res = ovl_getxattr(dentry, OVL_XATTR_REDIRECT, &buf, padding + 1); |
---|
935 | | - if (res == -ENODATA) |
---|
| 908 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); |
---|
| 909 | + if (res == -ENODATA || res == -EOPNOTSUPP) |
---|
936 | 910 | return NULL; |
---|
937 | 911 | if (res < 0) |
---|
938 | | - return ERR_PTR(res); |
---|
| 912 | + goto fail; |
---|
| 913 | + if (res == 0) |
---|
| 914 | + goto invalid; |
---|
| 915 | + |
---|
| 916 | + buf = kzalloc(res + padding + 1, GFP_KERNEL); |
---|
| 917 | + if (!buf) |
---|
| 918 | + return ERR_PTR(-ENOMEM); |
---|
| 919 | + |
---|
| 920 | + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); |
---|
| 921 | + if (res < 0) |
---|
| 922 | + goto fail; |
---|
939 | 923 | if (res == 0) |
---|
940 | 924 | goto invalid; |
---|
941 | 925 | |
---|
.. | .. |
---|
952 | 936 | |
---|
953 | 937 | return buf; |
---|
954 | 938 | invalid: |
---|
955 | | - pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); |
---|
| 939 | + pr_warn_ratelimited("invalid redirect (%s)\n", buf); |
---|
956 | 940 | res = -EINVAL; |
---|
| 941 | + goto err_free; |
---|
| 942 | +fail: |
---|
| 943 | + pr_warn_ratelimited("failed to get redirect (%i)\n", res); |
---|
| 944 | +err_free: |
---|
957 | 945 | kfree(buf); |
---|
958 | 946 | return ERR_PTR(res); |
---|
959 | 947 | } |
---|
| 948 | + |
---|
| 949 | +/* |
---|
| 950 | + * ovl_sync_status() - Check fs sync status for volatile mounts |
---|
| 951 | + * |
---|
| 952 | + * Returns 1 if this is not a volatile mount and a real sync is required. |
---|
| 953 | + * |
---|
| 954 | + * Returns 0 if syncing can be skipped because mount is volatile, and no errors |
---|
| 955 | + * have occurred on the upperdir since the mount. |
---|
| 956 | + * |
---|
| 957 | + * Returns -errno if it is a volatile mount, and the error that occurred since |
---|
| 958 | + * the last mount. If the error code changes, it'll return the latest error |
---|
| 959 | + * code. |
---|
| 960 | + */ |
---|
| 961 | + |
---|
| 962 | +int ovl_sync_status(struct ovl_fs *ofs) |
---|
| 963 | +{ |
---|
| 964 | + struct vfsmount *mnt; |
---|
| 965 | + |
---|
| 966 | + if (ovl_should_sync(ofs)) |
---|
| 967 | + return 1; |
---|
| 968 | + |
---|
| 969 | + mnt = ovl_upper_mnt(ofs); |
---|
| 970 | + if (!mnt) |
---|
| 971 | + return 0; |
---|
| 972 | + |
---|
| 973 | + return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq); |
---|
| 974 | +} |
---|