| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * This file is part of UBIFS. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2006-2008 Nokia Corporation. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 8 | | - * the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - * |
|---|
| 15 | | - * You should have received a copy of the GNU General Public License along with |
|---|
| 16 | | - * this program; if not, write to the Free Software Foundation, Inc., 51 |
|---|
| 17 | | - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 18 | 6 | * |
|---|
| 19 | 7 | * Author: Adrian Hunter |
|---|
| 20 | 8 | */ |
|---|
| .. | .. |
|---|
| 54 | 42 | |
|---|
| 55 | 43 | static int dbg_check_orphans(struct ubifs_info *c); |
|---|
| 56 | 44 | |
|---|
| 57 | | -/** |
|---|
| 58 | | - * ubifs_add_orphan - add an orphan. |
|---|
| 59 | | - * @c: UBIFS file-system description object |
|---|
| 60 | | - * @inum: orphan inode number |
|---|
| 61 | | - * |
|---|
| 62 | | - * Add an orphan. This function is called when an inodes link count drops to |
|---|
| 63 | | - * zero. |
|---|
| 64 | | - */ |
|---|
| 65 | | -int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 45 | +static struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum, |
|---|
| 46 | + struct ubifs_orphan *parent_orphan) |
|---|
| 66 | 47 | { |
|---|
| 67 | 48 | struct ubifs_orphan *orphan, *o; |
|---|
| 68 | 49 | struct rb_node **p, *parent = NULL; |
|---|
| 69 | 50 | |
|---|
| 70 | 51 | orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS); |
|---|
| 71 | 52 | if (!orphan) |
|---|
| 72 | | - return -ENOMEM; |
|---|
| 53 | + return ERR_PTR(-ENOMEM); |
|---|
| 73 | 54 | orphan->inum = inum; |
|---|
| 74 | 55 | orphan->new = 1; |
|---|
| 56 | + INIT_LIST_HEAD(&orphan->child_list); |
|---|
| 75 | 57 | |
|---|
| 76 | 58 | spin_lock(&c->orphan_lock); |
|---|
| 77 | 59 | if (c->tot_orphans >= c->max_orphans) { |
|---|
| 78 | 60 | spin_unlock(&c->orphan_lock); |
|---|
| 79 | 61 | kfree(orphan); |
|---|
| 80 | | - return -ENFILE; |
|---|
| 62 | + return ERR_PTR(-ENFILE); |
|---|
| 81 | 63 | } |
|---|
| 82 | 64 | p = &c->orph_tree.rb_node; |
|---|
| 83 | 65 | while (*p) { |
|---|
| .. | .. |
|---|
| 91 | 73 | ubifs_err(c, "orphaned twice"); |
|---|
| 92 | 74 | spin_unlock(&c->orphan_lock); |
|---|
| 93 | 75 | kfree(orphan); |
|---|
| 94 | | - return 0; |
|---|
| 76 | + return ERR_PTR(-EINVAL); |
|---|
| 95 | 77 | } |
|---|
| 96 | 78 | } |
|---|
| 97 | 79 | c->tot_orphans += 1; |
|---|
| .. | .. |
|---|
| 100 | 82 | rb_insert_color(&orphan->rb, &c->orph_tree); |
|---|
| 101 | 83 | list_add_tail(&orphan->list, &c->orph_list); |
|---|
| 102 | 84 | list_add_tail(&orphan->new_list, &c->orph_new); |
|---|
| 85 | + |
|---|
| 86 | + if (parent_orphan) { |
|---|
| 87 | + list_add_tail(&orphan->child_list, |
|---|
| 88 | + &parent_orphan->child_list); |
|---|
| 89 | + } |
|---|
| 90 | + |
|---|
| 103 | 91 | spin_unlock(&c->orphan_lock); |
|---|
| 104 | 92 | dbg_gen("ino %lu", (unsigned long)inum); |
|---|
| 93 | + return orphan; |
|---|
| 94 | +} |
|---|
| 95 | + |
|---|
| 96 | +static struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 97 | +{ |
|---|
| 98 | + struct ubifs_orphan *o; |
|---|
| 99 | + struct rb_node *p; |
|---|
| 100 | + |
|---|
| 101 | + p = c->orph_tree.rb_node; |
|---|
| 102 | + while (p) { |
|---|
| 103 | + o = rb_entry(p, struct ubifs_orphan, rb); |
|---|
| 104 | + if (inum < o->inum) |
|---|
| 105 | + p = p->rb_left; |
|---|
| 106 | + else if (inum > o->inum) |
|---|
| 107 | + p = p->rb_right; |
|---|
| 108 | + else { |
|---|
| 109 | + return o; |
|---|
| 110 | + } |
|---|
| 111 | + } |
|---|
| 112 | + return NULL; |
|---|
| 113 | +} |
|---|
| 114 | + |
|---|
| 115 | +static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o) |
|---|
| 116 | +{ |
|---|
| 117 | + rb_erase(&o->rb, &c->orph_tree); |
|---|
| 118 | + list_del(&o->list); |
|---|
| 119 | + c->tot_orphans -= 1; |
|---|
| 120 | + |
|---|
| 121 | + if (o->new) { |
|---|
| 122 | + list_del(&o->new_list); |
|---|
| 123 | + c->new_orphans -= 1; |
|---|
| 124 | + } |
|---|
| 125 | + |
|---|
| 126 | + kfree(o); |
|---|
| 127 | +} |
|---|
| 128 | + |
|---|
| 129 | +static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) |
|---|
| 130 | +{ |
|---|
| 131 | + if (orph->del) { |
|---|
| 132 | + dbg_gen("deleted twice ino %lu", (unsigned long)orph->inum); |
|---|
| 133 | + return; |
|---|
| 134 | + } |
|---|
| 135 | + |
|---|
| 136 | + if (orph->cmt) { |
|---|
| 137 | + orph->del = 1; |
|---|
| 138 | + orph->dnext = c->orph_dnext; |
|---|
| 139 | + c->orph_dnext = orph; |
|---|
| 140 | + dbg_gen("delete later ino %lu", (unsigned long)orph->inum); |
|---|
| 141 | + return; |
|---|
| 142 | + } |
|---|
| 143 | + |
|---|
| 144 | + __orphan_drop(c, orph); |
|---|
| 145 | +} |
|---|
| 146 | + |
|---|
| 147 | +/** |
|---|
| 148 | + * ubifs_add_orphan - add an orphan. |
|---|
| 149 | + * @c: UBIFS file-system description object |
|---|
| 150 | + * @inum: orphan inode number |
|---|
| 151 | + * |
|---|
| 152 | + * Add an orphan. This function is called when an inodes link count drops to |
|---|
| 153 | + * zero. |
|---|
| 154 | + */ |
|---|
| 155 | +int ubifs_add_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 156 | +{ |
|---|
| 157 | + int err = 0; |
|---|
| 158 | + ino_t xattr_inum; |
|---|
| 159 | + union ubifs_key key; |
|---|
| 160 | + struct ubifs_dent_node *xent, *pxent = NULL; |
|---|
| 161 | + struct fscrypt_name nm = {0}; |
|---|
| 162 | + struct ubifs_orphan *xattr_orphan; |
|---|
| 163 | + struct ubifs_orphan *orphan; |
|---|
| 164 | + |
|---|
| 165 | + orphan = orphan_add(c, inum, NULL); |
|---|
| 166 | + if (IS_ERR(orphan)) |
|---|
| 167 | + return PTR_ERR(orphan); |
|---|
| 168 | + |
|---|
| 169 | + lowest_xent_key(c, &key, inum); |
|---|
| 170 | + while (1) { |
|---|
| 171 | + xent = ubifs_tnc_next_ent(c, &key, &nm); |
|---|
| 172 | + if (IS_ERR(xent)) { |
|---|
| 173 | + err = PTR_ERR(xent); |
|---|
| 174 | + if (err == -ENOENT) |
|---|
| 175 | + break; |
|---|
| 176 | + kfree(pxent); |
|---|
| 177 | + return err; |
|---|
| 178 | + } |
|---|
| 179 | + |
|---|
| 180 | + fname_name(&nm) = xent->name; |
|---|
| 181 | + fname_len(&nm) = le16_to_cpu(xent->nlen); |
|---|
| 182 | + xattr_inum = le64_to_cpu(xent->inum); |
|---|
| 183 | + |
|---|
| 184 | + xattr_orphan = orphan_add(c, xattr_inum, orphan); |
|---|
| 185 | + if (IS_ERR(xattr_orphan)) { |
|---|
| 186 | + kfree(pxent); |
|---|
| 187 | + kfree(xent); |
|---|
| 188 | + return PTR_ERR(xattr_orphan); |
|---|
| 189 | + } |
|---|
| 190 | + |
|---|
| 191 | + kfree(pxent); |
|---|
| 192 | + pxent = xent; |
|---|
| 193 | + key_read(c, &xent->key, &key); |
|---|
| 194 | + } |
|---|
| 195 | + kfree(pxent); |
|---|
| 196 | + |
|---|
| 105 | 197 | return 0; |
|---|
| 106 | 198 | } |
|---|
| 107 | 199 | |
|---|
| .. | .. |
|---|
| 114 | 206 | */ |
|---|
| 115 | 207 | void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 116 | 208 | { |
|---|
| 117 | | - struct ubifs_orphan *o; |
|---|
| 118 | | - struct rb_node *p; |
|---|
| 209 | + struct ubifs_orphan *orph, *child_orph, *tmp_o; |
|---|
| 119 | 210 | |
|---|
| 120 | 211 | spin_lock(&c->orphan_lock); |
|---|
| 121 | | - p = c->orph_tree.rb_node; |
|---|
| 122 | | - while (p) { |
|---|
| 123 | | - o = rb_entry(p, struct ubifs_orphan, rb); |
|---|
| 124 | | - if (inum < o->inum) |
|---|
| 125 | | - p = p->rb_left; |
|---|
| 126 | | - else if (inum > o->inum) |
|---|
| 127 | | - p = p->rb_right; |
|---|
| 128 | | - else { |
|---|
| 129 | | - if (o->del) { |
|---|
| 130 | | - spin_unlock(&c->orphan_lock); |
|---|
| 131 | | - dbg_gen("deleted twice ino %lu", |
|---|
| 132 | | - (unsigned long)inum); |
|---|
| 133 | | - return; |
|---|
| 134 | | - } |
|---|
| 135 | | - if (o->cmt) { |
|---|
| 136 | | - o->del = 1; |
|---|
| 137 | | - o->dnext = c->orph_dnext; |
|---|
| 138 | | - c->orph_dnext = o; |
|---|
| 139 | | - spin_unlock(&c->orphan_lock); |
|---|
| 140 | | - dbg_gen("delete later ino %lu", |
|---|
| 141 | | - (unsigned long)inum); |
|---|
| 142 | | - return; |
|---|
| 143 | | - } |
|---|
| 144 | | - rb_erase(p, &c->orph_tree); |
|---|
| 145 | | - list_del(&o->list); |
|---|
| 146 | | - c->tot_orphans -= 1; |
|---|
| 147 | | - if (o->new) { |
|---|
| 148 | | - list_del(&o->new_list); |
|---|
| 149 | | - c->new_orphans -= 1; |
|---|
| 150 | | - } |
|---|
| 151 | | - spin_unlock(&c->orphan_lock); |
|---|
| 152 | | - kfree(o); |
|---|
| 153 | | - dbg_gen("inum %lu", (unsigned long)inum); |
|---|
| 154 | | - return; |
|---|
| 155 | | - } |
|---|
| 212 | + |
|---|
| 213 | + orph = lookup_orphan(c, inum); |
|---|
| 214 | + if (!orph) { |
|---|
| 215 | + spin_unlock(&c->orphan_lock); |
|---|
| 216 | + ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); |
|---|
| 217 | + dump_stack(); |
|---|
| 218 | + |
|---|
| 219 | + return; |
|---|
| 156 | 220 | } |
|---|
| 221 | + |
|---|
| 222 | + list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) { |
|---|
| 223 | + list_del(&child_orph->child_list); |
|---|
| 224 | + orphan_delete(c, child_orph); |
|---|
| 225 | + } |
|---|
| 226 | + |
|---|
| 227 | + orphan_delete(c, orph); |
|---|
| 228 | + |
|---|
| 157 | 229 | spin_unlock(&c->orphan_lock); |
|---|
| 158 | | - ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); |
|---|
| 159 | | - dump_stack(); |
|---|
| 160 | 230 | } |
|---|
| 161 | 231 | |
|---|
| 162 | 232 | /** |
|---|
| .. | .. |
|---|
| 563 | 633 | { |
|---|
| 564 | 634 | struct ubifs_scan_node *snod; |
|---|
| 565 | 635 | struct ubifs_orph_node *orph; |
|---|
| 636 | + struct ubifs_ino_node *ino = NULL; |
|---|
| 566 | 637 | unsigned long long cmt_no; |
|---|
| 567 | 638 | ino_t inum; |
|---|
| 568 | 639 | int i, n, err, first = 1; |
|---|
| 640 | + |
|---|
| 641 | + ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); |
|---|
| 642 | + if (!ino) |
|---|
| 643 | + return -ENOMEM; |
|---|
| 569 | 644 | |
|---|
| 570 | 645 | list_for_each_entry(snod, &sleb->nodes, list) { |
|---|
| 571 | 646 | if (snod->type != UBIFS_ORPH_NODE) { |
|---|
| 572 | 647 | ubifs_err(c, "invalid node type %d in orphan area at %d:%d", |
|---|
| 573 | 648 | snod->type, sleb->lnum, snod->offs); |
|---|
| 574 | 649 | ubifs_dump_node(c, snod->node); |
|---|
| 575 | | - return -EINVAL; |
|---|
| 650 | + err = -EINVAL; |
|---|
| 651 | + goto out_free; |
|---|
| 576 | 652 | } |
|---|
| 577 | 653 | |
|---|
| 578 | 654 | orph = snod->node; |
|---|
| .. | .. |
|---|
| 599 | 675 | ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d", |
|---|
| 600 | 676 | cmt_no, sleb->lnum, snod->offs); |
|---|
| 601 | 677 | ubifs_dump_node(c, snod->node); |
|---|
| 602 | | - return -EINVAL; |
|---|
| 678 | + err = -EINVAL; |
|---|
| 679 | + goto out_free; |
|---|
| 603 | 680 | } |
|---|
| 604 | 681 | dbg_rcvry("out of date LEB %d", sleb->lnum); |
|---|
| 605 | 682 | *outofdate = 1; |
|---|
| 606 | | - return 0; |
|---|
| 683 | + err = 0; |
|---|
| 684 | + goto out_free; |
|---|
| 607 | 685 | } |
|---|
| 608 | 686 | |
|---|
| 609 | 687 | if (first) |
|---|
| .. | .. |
|---|
| 611 | 689 | |
|---|
| 612 | 690 | n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; |
|---|
| 613 | 691 | for (i = 0; i < n; i++) { |
|---|
| 692 | + union ubifs_key key1, key2; |
|---|
| 693 | + |
|---|
| 614 | 694 | inum = le64_to_cpu(orph->inos[i]); |
|---|
| 615 | | - dbg_rcvry("deleting orphaned inode %lu", |
|---|
| 616 | | - (unsigned long)inum); |
|---|
| 617 | | - err = ubifs_tnc_remove_ino(c, inum); |
|---|
| 618 | | - if (err) |
|---|
| 619 | | - return err; |
|---|
| 695 | + |
|---|
| 696 | + ino_key_init(c, &key1, inum); |
|---|
| 697 | + err = ubifs_tnc_lookup(c, &key1, ino); |
|---|
| 698 | + if (err && err != -ENOENT) |
|---|
| 699 | + goto out_free; |
|---|
| 700 | + |
|---|
| 701 | + /* |
|---|
| 702 | + * Check whether an inode can really get deleted. |
|---|
| 703 | + * linkat() with O_TMPFILE allows rebirth of an inode. |
|---|
| 704 | + */ |
|---|
| 705 | + if (err == 0 && ino->nlink == 0) { |
|---|
| 706 | + dbg_rcvry("deleting orphaned inode %lu", |
|---|
| 707 | + (unsigned long)inum); |
|---|
| 708 | + |
|---|
| 709 | + lowest_ino_key(c, &key1, inum); |
|---|
| 710 | + highest_ino_key(c, &key2, inum); |
|---|
| 711 | + |
|---|
| 712 | + err = ubifs_tnc_remove_range(c, &key1, &key2); |
|---|
| 713 | + if (err) |
|---|
| 714 | + goto out_ro; |
|---|
| 715 | + } |
|---|
| 716 | + |
|---|
| 620 | 717 | err = insert_dead_orphan(c, inum); |
|---|
| 621 | 718 | if (err) |
|---|
| 622 | | - return err; |
|---|
| 719 | + goto out_free; |
|---|
| 623 | 720 | } |
|---|
| 624 | 721 | |
|---|
| 625 | 722 | *last_cmt_no = cmt_no; |
|---|
| .. | .. |
|---|
| 631 | 728 | *last_flagged = 0; |
|---|
| 632 | 729 | } |
|---|
| 633 | 730 | |
|---|
| 634 | | - return 0; |
|---|
| 731 | + err = 0; |
|---|
| 732 | +out_free: |
|---|
| 733 | + kfree(ino); |
|---|
| 734 | + return err; |
|---|
| 735 | + |
|---|
| 736 | +out_ro: |
|---|
| 737 | + ubifs_ro_mode(c, err); |
|---|
| 738 | + kfree(ino); |
|---|
| 739 | + return err; |
|---|
| 635 | 740 | } |
|---|
| 636 | 741 | |
|---|
| 637 | 742 | /** |
|---|
| .. | .. |
|---|
| 744 | 849 | struct rb_root root; |
|---|
| 745 | 850 | }; |
|---|
| 746 | 851 | |
|---|
| 747 | | -static int dbg_find_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 852 | +static bool dbg_find_orphan(struct ubifs_info *c, ino_t inum) |
|---|
| 748 | 853 | { |
|---|
| 749 | | - struct ubifs_orphan *o; |
|---|
| 750 | | - struct rb_node *p; |
|---|
| 854 | + bool found = false; |
|---|
| 751 | 855 | |
|---|
| 752 | 856 | spin_lock(&c->orphan_lock); |
|---|
| 753 | | - p = c->orph_tree.rb_node; |
|---|
| 754 | | - while (p) { |
|---|
| 755 | | - o = rb_entry(p, struct ubifs_orphan, rb); |
|---|
| 756 | | - if (inum < o->inum) |
|---|
| 757 | | - p = p->rb_left; |
|---|
| 758 | | - else if (inum > o->inum) |
|---|
| 759 | | - p = p->rb_right; |
|---|
| 760 | | - else { |
|---|
| 761 | | - spin_unlock(&c->orphan_lock); |
|---|
| 762 | | - return 1; |
|---|
| 763 | | - } |
|---|
| 764 | | - } |
|---|
| 857 | + found = !!lookup_orphan(c, inum); |
|---|
| 765 | 858 | spin_unlock(&c->orphan_lock); |
|---|
| 766 | | - return 0; |
|---|
| 859 | + |
|---|
| 860 | + return found; |
|---|
| 767 | 861 | } |
|---|
| 768 | 862 | |
|---|
| 769 | 863 | static int dbg_ins_check_orphan(struct rb_root *root, ino_t inum) |
|---|
| .. | .. |
|---|
| 885 | 979 | if (c->no_orphs) |
|---|
| 886 | 980 | return 0; |
|---|
| 887 | 981 | |
|---|
| 888 | | - buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); |
|---|
| 982 | + buf = __vmalloc(c->leb_size, GFP_NOFS); |
|---|
| 889 | 983 | if (!buf) { |
|---|
| 890 | 984 | ubifs_err(c, "cannot allocate memory to check orphans"); |
|---|
| 891 | 985 | return 0; |
|---|