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