| .. | .. |
|---|
| 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 | +} |
|---|