| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2011 Novell 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> |
|---|
| .. | .. |
|---|
| 289 | 286 | } |
|---|
| 290 | 287 | inode_unlock(dir->d_inode); |
|---|
| 291 | 288 | } |
|---|
| 292 | | - ovl_revert_creds(old_cred); |
|---|
| 289 | + ovl_revert_creds(rdd->dentry->d_sb, old_cred); |
|---|
| 293 | 290 | |
|---|
| 294 | 291 | return err; |
|---|
| 295 | 292 | } |
|---|
| .. | .. |
|---|
| 300 | 297 | struct file *realfile; |
|---|
| 301 | 298 | int err; |
|---|
| 302 | 299 | |
|---|
| 303 | | - realfile = ovl_path_open(realpath, O_RDONLY | O_DIRECTORY); |
|---|
| 300 | + realfile = ovl_path_open(realpath, O_RDONLY | O_LARGEFILE); |
|---|
| 304 | 301 | if (IS_ERR(realfile)) |
|---|
| 305 | 302 | return PTR_ERR(realfile); |
|---|
| 306 | 303 | |
|---|
| .. | .. |
|---|
| 320 | 317 | fput(realfile); |
|---|
| 321 | 318 | |
|---|
| 322 | 319 | return err; |
|---|
| 323 | | -} |
|---|
| 324 | | - |
|---|
| 325 | | -/* |
|---|
| 326 | | - * Can we iterate real dir directly? |
|---|
| 327 | | - * |
|---|
| 328 | | - * Non-merge dir may contain whiteouts from a time it was a merge upper, before |
|---|
| 329 | | - * lower dir was removed under it and possibly before it was rotated from upper |
|---|
| 330 | | - * to lower layer. |
|---|
| 331 | | - */ |
|---|
| 332 | | -static bool ovl_dir_is_real(struct dentry *dir) |
|---|
| 333 | | -{ |
|---|
| 334 | | - return !ovl_test_flag(OVL_WHITEOUTS, d_inode(dir)); |
|---|
| 335 | 320 | } |
|---|
| 336 | 321 | |
|---|
| 337 | 322 | static void ovl_dir_reset(struct file *file) |
|---|
| .. | .. |
|---|
| 441 | 426 | |
|---|
| 442 | 427 | /* Map inode number to lower fs unique range */ |
|---|
| 443 | 428 | static u64 ovl_remap_lower_ino(u64 ino, int xinobits, int fsid, |
|---|
| 444 | | - const char *name, int namelen) |
|---|
| 429 | + const char *name, int namelen, bool warn) |
|---|
| 445 | 430 | { |
|---|
| 446 | | - if (ino >> (64 - xinobits)) { |
|---|
| 447 | | - pr_warn_ratelimited("overlayfs: d_ino too big (%.*s, ino=%llu, xinobits=%d)\n", |
|---|
| 448 | | - namelen, name, ino, xinobits); |
|---|
| 431 | + unsigned int xinoshift = 64 - xinobits; |
|---|
| 432 | + |
|---|
| 433 | + if (unlikely(ino >> xinoshift)) { |
|---|
| 434 | + if (warn) { |
|---|
| 435 | + pr_warn_ratelimited("d_ino too big (%.*s, ino=%llu, xinobits=%d)\n", |
|---|
| 436 | + namelen, name, ino, xinobits); |
|---|
| 437 | + } |
|---|
| 449 | 438 | return ino; |
|---|
| 450 | 439 | } |
|---|
| 451 | 440 | |
|---|
| 452 | | - return ino | ((u64)fsid) << (64 - xinobits); |
|---|
| 441 | + /* |
|---|
| 442 | + * The lowest xinobit is reserved for mapping the non-peresistent inode |
|---|
| 443 | + * numbers range, but this range is only exposed via st_ino, not here. |
|---|
| 444 | + */ |
|---|
| 445 | + return ino | ((u64)fsid) << (xinoshift + 1); |
|---|
| 453 | 446 | } |
|---|
| 454 | 447 | |
|---|
| 455 | 448 | /* |
|---|
| .. | .. |
|---|
| 472 | 465 | int xinobits = ovl_xino_bits(dir->d_sb); |
|---|
| 473 | 466 | int err = 0; |
|---|
| 474 | 467 | |
|---|
| 475 | | - if (!ovl_same_sb(dir->d_sb) && !xinobits) |
|---|
| 468 | + if (!ovl_same_dev(dir->d_sb)) |
|---|
| 476 | 469 | goto out; |
|---|
| 477 | 470 | |
|---|
| 478 | 471 | if (p->name[0] == '.') { |
|---|
| .. | .. |
|---|
| 518 | 511 | } else if (xinobits && !OVL_TYPE_UPPER(type)) { |
|---|
| 519 | 512 | ino = ovl_remap_lower_ino(ino, xinobits, |
|---|
| 520 | 513 | ovl_layer_lower(this)->fsid, |
|---|
| 521 | | - p->name, p->len); |
|---|
| 514 | + p->name, p->len, |
|---|
| 515 | + ovl_xino_warn(dir->d_sb)); |
|---|
| 522 | 516 | } |
|---|
| 523 | 517 | |
|---|
| 524 | 518 | out: |
|---|
| .. | .. |
|---|
| 527 | 521 | return err; |
|---|
| 528 | 522 | |
|---|
| 529 | 523 | fail: |
|---|
| 530 | | - pr_warn_ratelimited("overlayfs: failed to look up (%s) for ino (%i)\n", |
|---|
| 524 | + pr_warn_ratelimited("failed to look up (%s) for ino (%i)\n", |
|---|
| 531 | 525 | p->name, err); |
|---|
| 532 | 526 | goto out; |
|---|
| 533 | 527 | } |
|---|
| .. | .. |
|---|
| 600 | 594 | { |
|---|
| 601 | 595 | int res; |
|---|
| 602 | 596 | struct dentry *dentry = path->dentry; |
|---|
| 597 | + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); |
|---|
| 603 | 598 | struct ovl_dir_cache *cache; |
|---|
| 604 | 599 | |
|---|
| 605 | 600 | cache = ovl_dir_cache(d_inode(dentry)); |
|---|
| .. | .. |
|---|
| 626 | 621 | * Removing the "impure" xattr is best effort. |
|---|
| 627 | 622 | */ |
|---|
| 628 | 623 | if (!ovl_want_write(dentry)) { |
|---|
| 629 | | - ovl_do_removexattr(ovl_dentry_upper(dentry), |
|---|
| 624 | + ovl_do_removexattr(ofs, ovl_dentry_upper(dentry), |
|---|
| 630 | 625 | OVL_XATTR_IMPURE); |
|---|
| 631 | 626 | ovl_drop_write(dentry); |
|---|
| 632 | 627 | } |
|---|
| .. | .. |
|---|
| 648 | 643 | u64 parent_ino; |
|---|
| 649 | 644 | int fsid; |
|---|
| 650 | 645 | int xinobits; |
|---|
| 646 | + bool xinowarn; |
|---|
| 651 | 647 | }; |
|---|
| 652 | 648 | |
|---|
| 653 | 649 | static int ovl_fill_real(struct dir_context *ctx, const char *name, |
|---|
| .. | .. |
|---|
| 668 | 664 | ino = p->ino; |
|---|
| 669 | 665 | } else if (rdt->xinobits) { |
|---|
| 670 | 666 | ino = ovl_remap_lower_ino(ino, rdt->xinobits, rdt->fsid, |
|---|
| 671 | | - name, namelen); |
|---|
| 667 | + name, namelen, rdt->xinowarn); |
|---|
| 672 | 668 | } |
|---|
| 673 | 669 | |
|---|
| 674 | 670 | return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type); |
|---|
| .. | .. |
|---|
| 694 | 690 | int err; |
|---|
| 695 | 691 | struct ovl_dir_file *od = file->private_data; |
|---|
| 696 | 692 | struct dentry *dir = file->f_path.dentry; |
|---|
| 697 | | - struct ovl_layer *lower_layer = ovl_layer_lower(dir); |
|---|
| 693 | + const struct ovl_layer *lower_layer = ovl_layer_lower(dir); |
|---|
| 698 | 694 | struct ovl_readdir_translate rdt = { |
|---|
| 699 | 695 | .ctx.actor = ovl_fill_real, |
|---|
| 700 | 696 | .orig_ctx = ctx, |
|---|
| 701 | 697 | .xinobits = ovl_xino_bits(dir->d_sb), |
|---|
| 698 | + .xinowarn = ovl_xino_warn(dir->d_sb), |
|---|
| 702 | 699 | }; |
|---|
| 703 | 700 | |
|---|
| 704 | 701 | if (rdt.xinobits && lower_layer) |
|---|
| .. | .. |
|---|
| 735 | 732 | struct ovl_dir_file *od = file->private_data; |
|---|
| 736 | 733 | struct dentry *dentry = file->f_path.dentry; |
|---|
| 737 | 734 | struct ovl_cache_entry *p; |
|---|
| 735 | + const struct cred *old_cred; |
|---|
| 738 | 736 | int err; |
|---|
| 739 | 737 | |
|---|
| 738 | + old_cred = ovl_override_creds(dentry->d_sb); |
|---|
| 740 | 739 | if (!ctx->pos) |
|---|
| 741 | 740 | ovl_dir_reset(file); |
|---|
| 742 | 741 | |
|---|
| .. | .. |
|---|
| 747 | 746 | * entries. |
|---|
| 748 | 747 | */ |
|---|
| 749 | 748 | if (ovl_xino_bits(dentry->d_sb) || |
|---|
| 750 | | - (ovl_same_sb(dentry->d_sb) && |
|---|
| 749 | + (ovl_same_fs(dentry->d_sb) && |
|---|
| 751 | 750 | (ovl_is_impure_dir(file) || |
|---|
| 752 | 751 | OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) { |
|---|
| 753 | | - return ovl_iterate_real(file, ctx); |
|---|
| 752 | + err = ovl_iterate_real(file, ctx); |
|---|
| 753 | + } else { |
|---|
| 754 | + err = iterate_dir(od->realfile, ctx); |
|---|
| 754 | 755 | } |
|---|
| 755 | | - return iterate_dir(od->realfile, ctx); |
|---|
| 756 | + goto out; |
|---|
| 756 | 757 | } |
|---|
| 757 | 758 | |
|---|
| 758 | 759 | if (!od->cache) { |
|---|
| 759 | 760 | struct ovl_dir_cache *cache; |
|---|
| 760 | 761 | |
|---|
| 761 | 762 | cache = ovl_cache_get(dentry); |
|---|
| 763 | + err = PTR_ERR(cache); |
|---|
| 762 | 764 | if (IS_ERR(cache)) |
|---|
| 763 | | - return PTR_ERR(cache); |
|---|
| 765 | + goto out; |
|---|
| 764 | 766 | |
|---|
| 765 | 767 | od->cache = cache; |
|---|
| 766 | 768 | ovl_seek_cursor(od, ctx->pos); |
|---|
| .. | .. |
|---|
| 772 | 774 | if (!p->ino) { |
|---|
| 773 | 775 | err = ovl_cache_update_ino(&file->f_path, p); |
|---|
| 774 | 776 | if (err) |
|---|
| 775 | | - return err; |
|---|
| 777 | + goto out; |
|---|
| 776 | 778 | } |
|---|
| 777 | 779 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) |
|---|
| 778 | 780 | break; |
|---|
| .. | .. |
|---|
| 780 | 782 | od->cursor = p->l_node.next; |
|---|
| 781 | 783 | ctx->pos++; |
|---|
| 782 | 784 | } |
|---|
| 783 | | - return 0; |
|---|
| 785 | + err = 0; |
|---|
| 786 | +out: |
|---|
| 787 | + ovl_revert_creds(dentry->d_sb, old_cred); |
|---|
| 788 | + return err; |
|---|
| 784 | 789 | } |
|---|
| 785 | 790 | |
|---|
| 786 | 791 | static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin) |
|---|
| .. | .. |
|---|
| 823 | 828 | return res; |
|---|
| 824 | 829 | } |
|---|
| 825 | 830 | |
|---|
| 826 | | -static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, |
|---|
| 827 | | - int datasync) |
|---|
| 831 | +static struct file *ovl_dir_open_realfile(const struct file *file, |
|---|
| 832 | + struct path *realpath) |
|---|
| 828 | 833 | { |
|---|
| 834 | + struct file *res; |
|---|
| 835 | + const struct cred *old_cred; |
|---|
| 836 | + |
|---|
| 837 | + old_cred = ovl_override_creds(file_inode(file)->i_sb); |
|---|
| 838 | + res = ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE)); |
|---|
| 839 | + ovl_revert_creds(file_inode(file)->i_sb, old_cred); |
|---|
| 840 | + |
|---|
| 841 | + return res; |
|---|
| 842 | +} |
|---|
| 843 | + |
|---|
| 844 | +/* |
|---|
| 845 | + * Like ovl_real_fdget(), returns upperfile if dir was copied up since open. |
|---|
| 846 | + * Unlike ovl_real_fdget(), this caches upperfile in file->private_data. |
|---|
| 847 | + * |
|---|
| 848 | + * TODO: use same abstract type for file->private_data of dir and file so |
|---|
| 849 | + * upperfile could also be cached for files as well. |
|---|
| 850 | + */ |
|---|
| 851 | +struct file *ovl_dir_real_file(const struct file *file, bool want_upper) |
|---|
| 852 | +{ |
|---|
| 853 | + |
|---|
| 829 | 854 | struct ovl_dir_file *od = file->private_data; |
|---|
| 830 | 855 | struct dentry *dentry = file->f_path.dentry; |
|---|
| 831 | | - struct file *realfile = od->realfile; |
|---|
| 856 | + struct file *old, *realfile = od->realfile; |
|---|
| 832 | 857 | |
|---|
| 833 | | - /* Nothing to sync for lower */ |
|---|
| 834 | 858 | if (!OVL_TYPE_UPPER(ovl_path_type(dentry))) |
|---|
| 835 | | - return 0; |
|---|
| 859 | + return want_upper ? NULL : realfile; |
|---|
| 836 | 860 | |
|---|
| 837 | 861 | /* |
|---|
| 838 | 862 | * Need to check if we started out being a lower dir, but got copied up |
|---|
| 839 | 863 | */ |
|---|
| 840 | 864 | if (!od->is_upper) { |
|---|
| 841 | | - struct inode *inode = file_inode(file); |
|---|
| 842 | | - |
|---|
| 843 | 865 | realfile = READ_ONCE(od->upperfile); |
|---|
| 844 | 866 | if (!realfile) { |
|---|
| 845 | 867 | struct path upperpath; |
|---|
| 846 | 868 | |
|---|
| 847 | 869 | ovl_path_upper(dentry, &upperpath); |
|---|
| 848 | | - realfile = ovl_path_open(&upperpath, O_RDONLY); |
|---|
| 870 | + realfile = ovl_dir_open_realfile(file, &upperpath); |
|---|
| 871 | + if (IS_ERR(realfile)) |
|---|
| 872 | + return realfile; |
|---|
| 849 | 873 | |
|---|
| 850 | | - inode_lock(inode); |
|---|
| 851 | | - if (!od->upperfile) { |
|---|
| 852 | | - if (IS_ERR(realfile)) { |
|---|
| 853 | | - inode_unlock(inode); |
|---|
| 854 | | - return PTR_ERR(realfile); |
|---|
| 855 | | - } |
|---|
| 856 | | - smp_store_release(&od->upperfile, realfile); |
|---|
| 857 | | - } else { |
|---|
| 858 | | - /* somebody has beaten us to it */ |
|---|
| 859 | | - if (!IS_ERR(realfile)) |
|---|
| 860 | | - fput(realfile); |
|---|
| 861 | | - realfile = od->upperfile; |
|---|
| 874 | + old = cmpxchg_release(&od->upperfile, NULL, realfile); |
|---|
| 875 | + if (old) { |
|---|
| 876 | + fput(realfile); |
|---|
| 877 | + realfile = old; |
|---|
| 862 | 878 | } |
|---|
| 863 | | - inode_unlock(inode); |
|---|
| 864 | 879 | } |
|---|
| 865 | 880 | } |
|---|
| 881 | + |
|---|
| 882 | + return realfile; |
|---|
| 883 | +} |
|---|
| 884 | + |
|---|
| 885 | +static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, |
|---|
| 886 | + int datasync) |
|---|
| 887 | +{ |
|---|
| 888 | + struct file *realfile; |
|---|
| 889 | + int err; |
|---|
| 890 | + |
|---|
| 891 | + err = ovl_sync_status(OVL_FS(file->f_path.dentry->d_sb)); |
|---|
| 892 | + if (err <= 0) |
|---|
| 893 | + return err; |
|---|
| 894 | + |
|---|
| 895 | + realfile = ovl_dir_real_file(file, true); |
|---|
| 896 | + err = PTR_ERR_OR_ZERO(realfile); |
|---|
| 897 | + |
|---|
| 898 | + /* Nothing to sync for lower */ |
|---|
| 899 | + if (!realfile || err) |
|---|
| 900 | + return err; |
|---|
| 866 | 901 | |
|---|
| 867 | 902 | return vfs_fsync_range(realfile, start, end, datasync); |
|---|
| 868 | 903 | } |
|---|
| .. | .. |
|---|
| 896 | 931 | return -ENOMEM; |
|---|
| 897 | 932 | |
|---|
| 898 | 933 | type = ovl_path_real(file->f_path.dentry, &realpath); |
|---|
| 899 | | - realfile = ovl_path_open(&realpath, file->f_flags); |
|---|
| 934 | + realfile = ovl_dir_open_realfile(file, &realpath); |
|---|
| 900 | 935 | if (IS_ERR(realfile)) { |
|---|
| 901 | 936 | kfree(od); |
|---|
| 902 | 937 | return PTR_ERR(realfile); |
|---|
| .. | .. |
|---|
| 916 | 951 | .llseek = ovl_dir_llseek, |
|---|
| 917 | 952 | .fsync = ovl_dir_fsync, |
|---|
| 918 | 953 | .release = ovl_dir_release, |
|---|
| 954 | + .unlocked_ioctl = ovl_ioctl, |
|---|
| 955 | +#ifdef CONFIG_COMPAT |
|---|
| 956 | + .compat_ioctl = ovl_compat_ioctl, |
|---|
| 957 | +#endif |
|---|
| 919 | 958 | }; |
|---|
| 920 | 959 | |
|---|
| 921 | 960 | int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) |
|---|
| .. | .. |
|---|
| 927 | 966 | |
|---|
| 928 | 967 | old_cred = ovl_override_creds(dentry->d_sb); |
|---|
| 929 | 968 | err = ovl_dir_read_merged(dentry, list, &root); |
|---|
| 930 | | - ovl_revert_creds(old_cred); |
|---|
| 969 | + ovl_revert_creds(dentry->d_sb, old_cred); |
|---|
| 931 | 970 | if (err) |
|---|
| 932 | 971 | return err; |
|---|
| 933 | 972 | |
|---|
| .. | .. |
|---|
| 974 | 1013 | |
|---|
| 975 | 1014 | dentry = lookup_one_len(p->name, upper, p->len); |
|---|
| 976 | 1015 | if (IS_ERR(dentry)) { |
|---|
| 977 | | - pr_err("overlayfs: lookup '%s/%.*s' failed (%i)\n", |
|---|
| 1016 | + pr_err("lookup '%s/%.*s' failed (%i)\n", |
|---|
| 978 | 1017 | upper->d_name.name, p->len, p->name, |
|---|
| 979 | 1018 | (int) PTR_ERR(dentry)); |
|---|
| 980 | 1019 | continue; |
|---|
| .. | .. |
|---|
| 1022 | 1061 | return rdd.d_type_supported; |
|---|
| 1023 | 1062 | } |
|---|
| 1024 | 1063 | |
|---|
| 1025 | | -static void ovl_workdir_cleanup_recurse(struct path *path, int level) |
|---|
| 1064 | +#define OVL_INCOMPATDIR_NAME "incompat" |
|---|
| 1065 | + |
|---|
| 1066 | +static int ovl_workdir_cleanup_recurse(struct path *path, int level) |
|---|
| 1026 | 1067 | { |
|---|
| 1027 | 1068 | int err; |
|---|
| 1028 | 1069 | struct inode *dir = path->dentry->d_inode; |
|---|
| .. | .. |
|---|
| 1036 | 1077 | .root = &root, |
|---|
| 1037 | 1078 | .is_lowest = false, |
|---|
| 1038 | 1079 | }; |
|---|
| 1080 | + bool incompat = false; |
|---|
| 1081 | + |
|---|
| 1082 | + /* |
|---|
| 1083 | + * The "work/incompat" directory is treated specially - if it is not |
|---|
| 1084 | + * empty, instead of printing a generic error and mounting read-only, |
|---|
| 1085 | + * we will error about incompat features and fail the mount. |
|---|
| 1086 | + * |
|---|
| 1087 | + * When called from ovl_indexdir_cleanup(), path->dentry->d_name.name |
|---|
| 1088 | + * starts with '#'. |
|---|
| 1089 | + */ |
|---|
| 1090 | + if (level == 2 && |
|---|
| 1091 | + !strcmp(path->dentry->d_name.name, OVL_INCOMPATDIR_NAME)) |
|---|
| 1092 | + incompat = true; |
|---|
| 1039 | 1093 | |
|---|
| 1040 | 1094 | err = ovl_dir_read(path, &rdd); |
|---|
| 1041 | 1095 | if (err) |
|---|
| .. | .. |
|---|
| 1050 | 1104 | continue; |
|---|
| 1051 | 1105 | if (p->len == 2 && p->name[1] == '.') |
|---|
| 1052 | 1106 | continue; |
|---|
| 1107 | + } else if (incompat) { |
|---|
| 1108 | + pr_err("overlay with incompat feature '%s' cannot be mounted\n", |
|---|
| 1109 | + p->name); |
|---|
| 1110 | + err = -EINVAL; |
|---|
| 1111 | + break; |
|---|
| 1053 | 1112 | } |
|---|
| 1054 | 1113 | dentry = lookup_one_len(p->name, path->dentry, p->len); |
|---|
| 1055 | 1114 | if (IS_ERR(dentry)) |
|---|
| 1056 | 1115 | continue; |
|---|
| 1057 | 1116 | if (dentry->d_inode) |
|---|
| 1058 | | - ovl_workdir_cleanup(dir, path->mnt, dentry, level); |
|---|
| 1117 | + err = ovl_workdir_cleanup(dir, path->mnt, dentry, level); |
|---|
| 1059 | 1118 | dput(dentry); |
|---|
| 1119 | + if (err) |
|---|
| 1120 | + break; |
|---|
| 1060 | 1121 | } |
|---|
| 1061 | 1122 | inode_unlock(dir); |
|---|
| 1062 | 1123 | out: |
|---|
| 1063 | 1124 | ovl_cache_free(&list); |
|---|
| 1125 | + return err; |
|---|
| 1064 | 1126 | } |
|---|
| 1065 | 1127 | |
|---|
| 1066 | | -void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, |
|---|
| 1128 | +int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, |
|---|
| 1067 | 1129 | struct dentry *dentry, int level) |
|---|
| 1068 | 1130 | { |
|---|
| 1069 | 1131 | int err; |
|---|
| 1070 | 1132 | |
|---|
| 1071 | 1133 | if (!d_is_dir(dentry) || level > 1) { |
|---|
| 1072 | | - ovl_cleanup(dir, dentry); |
|---|
| 1073 | | - return; |
|---|
| 1134 | + return ovl_cleanup(dir, dentry); |
|---|
| 1074 | 1135 | } |
|---|
| 1075 | 1136 | |
|---|
| 1076 | 1137 | err = ovl_do_rmdir(dir, dentry); |
|---|
| .. | .. |
|---|
| 1078 | 1139 | struct path path = { .mnt = mnt, .dentry = dentry }; |
|---|
| 1079 | 1140 | |
|---|
| 1080 | 1141 | inode_unlock(dir); |
|---|
| 1081 | | - ovl_workdir_cleanup_recurse(&path, level + 1); |
|---|
| 1142 | + err = ovl_workdir_cleanup_recurse(&path, level + 1); |
|---|
| 1082 | 1143 | inode_lock_nested(dir, I_MUTEX_PARENT); |
|---|
| 1083 | | - ovl_cleanup(dir, dentry); |
|---|
| 1144 | + if (!err) |
|---|
| 1145 | + err = ovl_cleanup(dir, dentry); |
|---|
| 1084 | 1146 | } |
|---|
| 1147 | + |
|---|
| 1148 | + return err; |
|---|
| 1085 | 1149 | } |
|---|
| 1086 | 1150 | |
|---|
| 1087 | 1151 | int ovl_indexdir_cleanup(struct ovl_fs *ofs) |
|---|
| .. | .. |
|---|
| 1090 | 1154 | struct dentry *indexdir = ofs->indexdir; |
|---|
| 1091 | 1155 | struct dentry *index = NULL; |
|---|
| 1092 | 1156 | struct inode *dir = indexdir->d_inode; |
|---|
| 1093 | | - struct path path = { .mnt = ofs->upper_mnt, .dentry = indexdir }; |
|---|
| 1157 | + struct path path = { .mnt = ovl_upper_mnt(ofs), .dentry = indexdir }; |
|---|
| 1094 | 1158 | LIST_HEAD(list); |
|---|
| 1095 | 1159 | struct rb_root root = RB_ROOT; |
|---|
| 1096 | 1160 | struct ovl_cache_entry *p; |
|---|
| .. | .. |
|---|
| 1120 | 1184 | index = NULL; |
|---|
| 1121 | 1185 | break; |
|---|
| 1122 | 1186 | } |
|---|
| 1187 | + /* Cleanup leftover from index create/cleanup attempt */ |
|---|
| 1188 | + if (index->d_name.name[0] == '#') { |
|---|
| 1189 | + err = ovl_workdir_cleanup(dir, path.mnt, index, 1); |
|---|
| 1190 | + if (err) |
|---|
| 1191 | + break; |
|---|
| 1192 | + goto next; |
|---|
| 1193 | + } |
|---|
| 1123 | 1194 | err = ovl_verify_index(ofs, index); |
|---|
| 1124 | 1195 | if (!err) { |
|---|
| 1125 | 1196 | goto next; |
|---|
| .. | .. |
|---|
| 1138 | 1209 | * Whiteout orphan index to block future open by |
|---|
| 1139 | 1210 | * handle after overlay nlink dropped to zero. |
|---|
| 1140 | 1211 | */ |
|---|
| 1141 | | - err = ovl_cleanup_and_whiteout(indexdir, dir, index); |
|---|
| 1212 | + err = ovl_cleanup_and_whiteout(ofs, dir, index); |
|---|
| 1142 | 1213 | } else { |
|---|
| 1143 | 1214 | /* Cleanup orphan index entries */ |
|---|
| 1144 | 1215 | err = ovl_cleanup(dir, index); |
|---|
| .. | .. |
|---|
| 1156 | 1227 | out: |
|---|
| 1157 | 1228 | ovl_cache_free(&list); |
|---|
| 1158 | 1229 | if (err) |
|---|
| 1159 | | - pr_err("overlayfs: failed index dir cleanup (%i)\n", err); |
|---|
| 1230 | + pr_err("failed index dir cleanup (%i)\n", err); |
|---|
| 1160 | 1231 | return err; |
|---|
| 1161 | 1232 | } |
|---|