18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This file is part of UBIFS. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Adrian Hunter 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "ubifs.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* 138c2ecf20Sopenharmony_ci * An orphan is an inode number whose inode node has been committed to the index 148c2ecf20Sopenharmony_ci * with a link count of zero. That happens when an open file is deleted 158c2ecf20Sopenharmony_ci * (unlinked) and then a commit is run. In the normal course of events the inode 168c2ecf20Sopenharmony_ci * would be deleted when the file is closed. However in the case of an unclean 178c2ecf20Sopenharmony_ci * unmount, orphans need to be accounted for. After an unclean unmount, the 188c2ecf20Sopenharmony_ci * orphans' inodes must be deleted which means either scanning the entire index 198c2ecf20Sopenharmony_ci * looking for them, or keeping a list on flash somewhere. This unit implements 208c2ecf20Sopenharmony_ci * the latter approach. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * The orphan area is a fixed number of LEBs situated between the LPT area and 238c2ecf20Sopenharmony_ci * the main area. The number of orphan area LEBs is specified when the file 248c2ecf20Sopenharmony_ci * system is created. The minimum number is 1. The size of the orphan area 258c2ecf20Sopenharmony_ci * should be so that it can hold the maximum number of orphans that are expected 268c2ecf20Sopenharmony_ci * to ever exist at one time. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * The number of orphans that can fit in a LEB is: 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * (c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64) 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * For example: a 15872 byte LEB can fit 1980 orphans so 1 LEB may be enough. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Orphans are accumulated in a rb-tree. When an inode's link count drops to 358c2ecf20Sopenharmony_ci * zero, the inode number is added to the rb-tree. It is removed from the tree 368c2ecf20Sopenharmony_ci * when the inode is deleted. Any new orphans that are in the orphan tree when 378c2ecf20Sopenharmony_ci * the commit is run, are written to the orphan area in 1 or more orphan nodes. 388c2ecf20Sopenharmony_ci * If the orphan area is full, it is consolidated to make space. There is 398c2ecf20Sopenharmony_ci * always enough space because validation prevents the user from creating more 408c2ecf20Sopenharmony_ci * than the maximum number of orphans allowed. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic int dbg_check_orphans(struct ubifs_info *c); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic struct ubifs_orphan *orphan_add(struct ubifs_info *c, ino_t inum, 468c2ecf20Sopenharmony_ci struct ubifs_orphan *parent_orphan) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, *o; 498c2ecf20Sopenharmony_ci struct rb_node **p, *parent = NULL; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_NOFS); 528c2ecf20Sopenharmony_ci if (!orphan) 538c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 548c2ecf20Sopenharmony_ci orphan->inum = inum; 558c2ecf20Sopenharmony_ci orphan->new = 1; 568c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&orphan->child_list); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 598c2ecf20Sopenharmony_ci if (c->tot_orphans >= c->max_orphans) { 608c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 618c2ecf20Sopenharmony_ci kfree(orphan); 628c2ecf20Sopenharmony_ci return ERR_PTR(-ENFILE); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci p = &c->orph_tree.rb_node; 658c2ecf20Sopenharmony_ci while (*p) { 668c2ecf20Sopenharmony_ci parent = *p; 678c2ecf20Sopenharmony_ci o = rb_entry(parent, struct ubifs_orphan, rb); 688c2ecf20Sopenharmony_ci if (inum < o->inum) 698c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 708c2ecf20Sopenharmony_ci else if (inum > o->inum) 718c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 728c2ecf20Sopenharmony_ci else { 738c2ecf20Sopenharmony_ci ubifs_err(c, "orphaned twice"); 748c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 758c2ecf20Sopenharmony_ci kfree(orphan); 768c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci c->tot_orphans += 1; 808c2ecf20Sopenharmony_ci c->new_orphans += 1; 818c2ecf20Sopenharmony_ci rb_link_node(&orphan->rb, parent, p); 828c2ecf20Sopenharmony_ci rb_insert_color(&orphan->rb, &c->orph_tree); 838c2ecf20Sopenharmony_ci list_add_tail(&orphan->list, &c->orph_list); 848c2ecf20Sopenharmony_ci list_add_tail(&orphan->new_list, &c->orph_new); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (parent_orphan) { 878c2ecf20Sopenharmony_ci list_add_tail(&orphan->child_list, 888c2ecf20Sopenharmony_ci &parent_orphan->child_list); 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 928c2ecf20Sopenharmony_ci dbg_gen("ino %lu", (unsigned long)inum); 938c2ecf20Sopenharmony_ci return orphan; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic struct ubifs_orphan *lookup_orphan(struct ubifs_info *c, ino_t inum) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct ubifs_orphan *o; 998c2ecf20Sopenharmony_ci struct rb_node *p; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci p = c->orph_tree.rb_node; 1028c2ecf20Sopenharmony_ci while (p) { 1038c2ecf20Sopenharmony_ci o = rb_entry(p, struct ubifs_orphan, rb); 1048c2ecf20Sopenharmony_ci if (inum < o->inum) 1058c2ecf20Sopenharmony_ci p = p->rb_left; 1068c2ecf20Sopenharmony_ci else if (inum > o->inum) 1078c2ecf20Sopenharmony_ci p = p->rb_right; 1088c2ecf20Sopenharmony_ci else { 1098c2ecf20Sopenharmony_ci return o; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci return NULL; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci rb_erase(&o->rb, &c->orph_tree); 1188c2ecf20Sopenharmony_ci list_del(&o->list); 1198c2ecf20Sopenharmony_ci c->tot_orphans -= 1; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (o->new) { 1228c2ecf20Sopenharmony_ci list_del(&o->new_list); 1238c2ecf20Sopenharmony_ci c->new_orphans -= 1; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci kfree(o); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci if (orph->del) { 1328c2ecf20Sopenharmony_ci dbg_gen("deleted twice ino %lu", (unsigned long)orph->inum); 1338c2ecf20Sopenharmony_ci return; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (orph->cmt) { 1378c2ecf20Sopenharmony_ci orph->del = 1; 1388c2ecf20Sopenharmony_ci orph->dnext = c->orph_dnext; 1398c2ecf20Sopenharmony_ci c->orph_dnext = orph; 1408c2ecf20Sopenharmony_ci dbg_gen("delete later ino %lu", (unsigned long)orph->inum); 1418c2ecf20Sopenharmony_ci return; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci __orphan_drop(c, orph); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/** 1488c2ecf20Sopenharmony_ci * ubifs_add_orphan - add an orphan. 1498c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 1508c2ecf20Sopenharmony_ci * @inum: orphan inode number 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * Add an orphan. This function is called when an inodes link count drops to 1538c2ecf20Sopenharmony_ci * zero. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ciint ubifs_add_orphan(struct ubifs_info *c, ino_t inum) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci int err = 0; 1588c2ecf20Sopenharmony_ci ino_t xattr_inum; 1598c2ecf20Sopenharmony_ci union ubifs_key key; 1608c2ecf20Sopenharmony_ci struct ubifs_dent_node *xent, *pxent = NULL; 1618c2ecf20Sopenharmony_ci struct fscrypt_name nm = {0}; 1628c2ecf20Sopenharmony_ci struct ubifs_orphan *xattr_orphan; 1638c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci orphan = orphan_add(c, inum, NULL); 1668c2ecf20Sopenharmony_ci if (IS_ERR(orphan)) 1678c2ecf20Sopenharmony_ci return PTR_ERR(orphan); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci lowest_xent_key(c, &key, inum); 1708c2ecf20Sopenharmony_ci while (1) { 1718c2ecf20Sopenharmony_ci xent = ubifs_tnc_next_ent(c, &key, &nm); 1728c2ecf20Sopenharmony_ci if (IS_ERR(xent)) { 1738c2ecf20Sopenharmony_ci err = PTR_ERR(xent); 1748c2ecf20Sopenharmony_ci if (err == -ENOENT) 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci kfree(pxent); 1778c2ecf20Sopenharmony_ci return err; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci fname_name(&nm) = xent->name; 1818c2ecf20Sopenharmony_ci fname_len(&nm) = le16_to_cpu(xent->nlen); 1828c2ecf20Sopenharmony_ci xattr_inum = le64_to_cpu(xent->inum); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci xattr_orphan = orphan_add(c, xattr_inum, orphan); 1858c2ecf20Sopenharmony_ci if (IS_ERR(xattr_orphan)) { 1868c2ecf20Sopenharmony_ci kfree(pxent); 1878c2ecf20Sopenharmony_ci kfree(xent); 1888c2ecf20Sopenharmony_ci return PTR_ERR(xattr_orphan); 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci kfree(pxent); 1928c2ecf20Sopenharmony_ci pxent = xent; 1938c2ecf20Sopenharmony_ci key_read(c, &xent->key, &key); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci kfree(pxent); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/** 2018c2ecf20Sopenharmony_ci * ubifs_delete_orphan - delete an orphan. 2028c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 2038c2ecf20Sopenharmony_ci * @inum: orphan inode number 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * Delete an orphan. This function is called when an inode is deleted. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_civoid ubifs_delete_orphan(struct ubifs_info *c, ino_t inum) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct ubifs_orphan *orph, *child_orph, *tmp_o; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci orph = lookup_orphan(c, inum); 2148c2ecf20Sopenharmony_ci if (!orph) { 2158c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 2168c2ecf20Sopenharmony_ci ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum); 2178c2ecf20Sopenharmony_ci dump_stack(); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci list_for_each_entry_safe(child_orph, tmp_o, &orph->child_list, child_list) { 2238c2ecf20Sopenharmony_ci list_del(&child_orph->child_list); 2248c2ecf20Sopenharmony_ci orphan_delete(c, child_orph); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci orphan_delete(c, orph); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/** 2338c2ecf20Sopenharmony_ci * ubifs_orphan_start_commit - start commit of orphans. 2348c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 2358c2ecf20Sopenharmony_ci * 2368c2ecf20Sopenharmony_ci * Start commit of orphans. 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_ciint ubifs_orphan_start_commit(struct ubifs_info *c) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, **last; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 2438c2ecf20Sopenharmony_ci last = &c->orph_cnext; 2448c2ecf20Sopenharmony_ci list_for_each_entry(orphan, &c->orph_new, new_list) { 2458c2ecf20Sopenharmony_ci ubifs_assert(c, orphan->new); 2468c2ecf20Sopenharmony_ci ubifs_assert(c, !orphan->cmt); 2478c2ecf20Sopenharmony_ci orphan->new = 0; 2488c2ecf20Sopenharmony_ci orphan->cmt = 1; 2498c2ecf20Sopenharmony_ci *last = orphan; 2508c2ecf20Sopenharmony_ci last = &orphan->cnext; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci *last = NULL; 2538c2ecf20Sopenharmony_ci c->cmt_orphans = c->new_orphans; 2548c2ecf20Sopenharmony_ci c->new_orphans = 0; 2558c2ecf20Sopenharmony_ci dbg_cmt("%d orphans to commit", c->cmt_orphans); 2568c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&c->orph_new); 2578c2ecf20Sopenharmony_ci if (c->tot_orphans == 0) 2588c2ecf20Sopenharmony_ci c->no_orphs = 1; 2598c2ecf20Sopenharmony_ci else 2608c2ecf20Sopenharmony_ci c->no_orphs = 0; 2618c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci/** 2668c2ecf20Sopenharmony_ci * avail_orphs - calculate available space. 2678c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 2688c2ecf20Sopenharmony_ci * 2698c2ecf20Sopenharmony_ci * This function returns the number of orphans that can be written in the 2708c2ecf20Sopenharmony_ci * available space. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_cistatic int avail_orphs(struct ubifs_info *c) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci int avail_lebs, avail, gap; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci avail_lebs = c->orph_lebs - (c->ohead_lnum - c->orph_first) - 1; 2778c2ecf20Sopenharmony_ci avail = avail_lebs * 2788c2ecf20Sopenharmony_ci ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)); 2798c2ecf20Sopenharmony_ci gap = c->leb_size - c->ohead_offs; 2808c2ecf20Sopenharmony_ci if (gap >= UBIFS_ORPH_NODE_SZ + sizeof(__le64)) 2818c2ecf20Sopenharmony_ci avail += (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64); 2828c2ecf20Sopenharmony_ci return avail; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci/** 2868c2ecf20Sopenharmony_ci * tot_avail_orphs - calculate total space. 2878c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 2888c2ecf20Sopenharmony_ci * 2898c2ecf20Sopenharmony_ci * This function returns the number of orphans that can be written in half 2908c2ecf20Sopenharmony_ci * the total space. That leaves half the space for adding new orphans. 2918c2ecf20Sopenharmony_ci */ 2928c2ecf20Sopenharmony_cistatic int tot_avail_orphs(struct ubifs_info *c) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci int avail_lebs, avail; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci avail_lebs = c->orph_lebs; 2978c2ecf20Sopenharmony_ci avail = avail_lebs * 2988c2ecf20Sopenharmony_ci ((c->leb_size - UBIFS_ORPH_NODE_SZ) / sizeof(__le64)); 2998c2ecf20Sopenharmony_ci return avail / 2; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci/** 3038c2ecf20Sopenharmony_ci * do_write_orph_node - write a node to the orphan head. 3048c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 3058c2ecf20Sopenharmony_ci * @len: length of node 3068c2ecf20Sopenharmony_ci * @atomic: write atomically 3078c2ecf20Sopenharmony_ci * 3088c2ecf20Sopenharmony_ci * This function writes a node to the orphan head from the orphan buffer. If 3098c2ecf20Sopenharmony_ci * %atomic is not zero, then the write is done atomically. On success, %0 is 3108c2ecf20Sopenharmony_ci * returned, otherwise a negative error code is returned. 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_cistatic int do_write_orph_node(struct ubifs_info *c, int len, int atomic) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci int err = 0; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (atomic) { 3178c2ecf20Sopenharmony_ci ubifs_assert(c, c->ohead_offs == 0); 3188c2ecf20Sopenharmony_ci ubifs_prepare_node(c, c->orph_buf, len, 1); 3198c2ecf20Sopenharmony_ci len = ALIGN(len, c->min_io_size); 3208c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len); 3218c2ecf20Sopenharmony_ci } else { 3228c2ecf20Sopenharmony_ci if (c->ohead_offs == 0) { 3238c2ecf20Sopenharmony_ci /* Ensure LEB has been unmapped */ 3248c2ecf20Sopenharmony_ci err = ubifs_leb_unmap(c, c->ohead_lnum); 3258c2ecf20Sopenharmony_ci if (err) 3268c2ecf20Sopenharmony_ci return err; 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum, 3298c2ecf20Sopenharmony_ci c->ohead_offs); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci return err; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci/** 3358c2ecf20Sopenharmony_ci * write_orph_node - write an orphan node. 3368c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 3378c2ecf20Sopenharmony_ci * @atomic: write atomically 3388c2ecf20Sopenharmony_ci * 3398c2ecf20Sopenharmony_ci * This function builds an orphan node from the cnext list and writes it to the 3408c2ecf20Sopenharmony_ci * orphan head. On success, %0 is returned, otherwise a negative error code 3418c2ecf20Sopenharmony_ci * is returned. 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_cistatic int write_orph_node(struct ubifs_info *c, int atomic) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, *cnext; 3468c2ecf20Sopenharmony_ci struct ubifs_orph_node *orph; 3478c2ecf20Sopenharmony_ci int gap, err, len, cnt, i; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci ubifs_assert(c, c->cmt_orphans > 0); 3508c2ecf20Sopenharmony_ci gap = c->leb_size - c->ohead_offs; 3518c2ecf20Sopenharmony_ci if (gap < UBIFS_ORPH_NODE_SZ + sizeof(__le64)) { 3528c2ecf20Sopenharmony_ci c->ohead_lnum += 1; 3538c2ecf20Sopenharmony_ci c->ohead_offs = 0; 3548c2ecf20Sopenharmony_ci gap = c->leb_size; 3558c2ecf20Sopenharmony_ci if (c->ohead_lnum > c->orph_last) { 3568c2ecf20Sopenharmony_ci /* 3578c2ecf20Sopenharmony_ci * We limit the number of orphans so that this should 3588c2ecf20Sopenharmony_ci * never happen. 3598c2ecf20Sopenharmony_ci */ 3608c2ecf20Sopenharmony_ci ubifs_err(c, "out of space in orphan area"); 3618c2ecf20Sopenharmony_ci return -EINVAL; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci cnt = (gap - UBIFS_ORPH_NODE_SZ) / sizeof(__le64); 3658c2ecf20Sopenharmony_ci if (cnt > c->cmt_orphans) 3668c2ecf20Sopenharmony_ci cnt = c->cmt_orphans; 3678c2ecf20Sopenharmony_ci len = UBIFS_ORPH_NODE_SZ + cnt * sizeof(__le64); 3688c2ecf20Sopenharmony_ci ubifs_assert(c, c->orph_buf); 3698c2ecf20Sopenharmony_ci orph = c->orph_buf; 3708c2ecf20Sopenharmony_ci orph->ch.node_type = UBIFS_ORPH_NODE; 3718c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 3728c2ecf20Sopenharmony_ci cnext = c->orph_cnext; 3738c2ecf20Sopenharmony_ci for (i = 0; i < cnt; i++) { 3748c2ecf20Sopenharmony_ci orphan = cnext; 3758c2ecf20Sopenharmony_ci ubifs_assert(c, orphan->cmt); 3768c2ecf20Sopenharmony_ci orph->inos[i] = cpu_to_le64(orphan->inum); 3778c2ecf20Sopenharmony_ci orphan->cmt = 0; 3788c2ecf20Sopenharmony_ci cnext = orphan->cnext; 3798c2ecf20Sopenharmony_ci orphan->cnext = NULL; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci c->orph_cnext = cnext; 3828c2ecf20Sopenharmony_ci c->cmt_orphans -= cnt; 3838c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 3848c2ecf20Sopenharmony_ci if (c->cmt_orphans) 3858c2ecf20Sopenharmony_ci orph->cmt_no = cpu_to_le64(c->cmt_no); 3868c2ecf20Sopenharmony_ci else 3878c2ecf20Sopenharmony_ci /* Mark the last node of the commit */ 3888c2ecf20Sopenharmony_ci orph->cmt_no = cpu_to_le64((c->cmt_no) | (1ULL << 63)); 3898c2ecf20Sopenharmony_ci ubifs_assert(c, c->ohead_offs + len <= c->leb_size); 3908c2ecf20Sopenharmony_ci ubifs_assert(c, c->ohead_lnum >= c->orph_first); 3918c2ecf20Sopenharmony_ci ubifs_assert(c, c->ohead_lnum <= c->orph_last); 3928c2ecf20Sopenharmony_ci err = do_write_orph_node(c, len, atomic); 3938c2ecf20Sopenharmony_ci c->ohead_offs += ALIGN(len, c->min_io_size); 3948c2ecf20Sopenharmony_ci c->ohead_offs = ALIGN(c->ohead_offs, 8); 3958c2ecf20Sopenharmony_ci return err; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci/** 3998c2ecf20Sopenharmony_ci * write_orph_nodes - write orphan nodes until there are no more to commit. 4008c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4018c2ecf20Sopenharmony_ci * @atomic: write atomically 4028c2ecf20Sopenharmony_ci * 4038c2ecf20Sopenharmony_ci * This function writes orphan nodes for all the orphans to commit. On success, 4048c2ecf20Sopenharmony_ci * %0 is returned, otherwise a negative error code is returned. 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_cistatic int write_orph_nodes(struct ubifs_info *c, int atomic) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci int err; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci while (c->cmt_orphans > 0) { 4118c2ecf20Sopenharmony_ci err = write_orph_node(c, atomic); 4128c2ecf20Sopenharmony_ci if (err) 4138c2ecf20Sopenharmony_ci return err; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci if (atomic) { 4168c2ecf20Sopenharmony_ci int lnum; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* Unmap any unused LEBs after consolidation */ 4198c2ecf20Sopenharmony_ci for (lnum = c->ohead_lnum + 1; lnum <= c->orph_last; lnum++) { 4208c2ecf20Sopenharmony_ci err = ubifs_leb_unmap(c, lnum); 4218c2ecf20Sopenharmony_ci if (err) 4228c2ecf20Sopenharmony_ci return err; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci return 0; 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/** 4298c2ecf20Sopenharmony_ci * consolidate - consolidate the orphan area. 4308c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4318c2ecf20Sopenharmony_ci * 4328c2ecf20Sopenharmony_ci * This function enables consolidation by putting all the orphans into the list 4338c2ecf20Sopenharmony_ci * to commit. The list is in the order that the orphans were added, and the 4348c2ecf20Sopenharmony_ci * LEBs are written atomically in order, so at no time can orphans be lost by 4358c2ecf20Sopenharmony_ci * an unclean unmount. 4368c2ecf20Sopenharmony_ci * 4378c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 4388c2ecf20Sopenharmony_ci */ 4398c2ecf20Sopenharmony_cistatic int consolidate(struct ubifs_info *c) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci int tot_avail = tot_avail_orphs(c), err = 0; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 4448c2ecf20Sopenharmony_ci dbg_cmt("there is space for %d orphans and there are %d", 4458c2ecf20Sopenharmony_ci tot_avail, c->tot_orphans); 4468c2ecf20Sopenharmony_ci if (c->tot_orphans - c->new_orphans <= tot_avail) { 4478c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, **last; 4488c2ecf20Sopenharmony_ci int cnt = 0; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* Change the cnext list to include all non-new orphans */ 4518c2ecf20Sopenharmony_ci last = &c->orph_cnext; 4528c2ecf20Sopenharmony_ci list_for_each_entry(orphan, &c->orph_list, list) { 4538c2ecf20Sopenharmony_ci if (orphan->new) 4548c2ecf20Sopenharmony_ci continue; 4558c2ecf20Sopenharmony_ci orphan->cmt = 1; 4568c2ecf20Sopenharmony_ci *last = orphan; 4578c2ecf20Sopenharmony_ci last = &orphan->cnext; 4588c2ecf20Sopenharmony_ci cnt += 1; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci *last = NULL; 4618c2ecf20Sopenharmony_ci ubifs_assert(c, cnt == c->tot_orphans - c->new_orphans); 4628c2ecf20Sopenharmony_ci c->cmt_orphans = cnt; 4638c2ecf20Sopenharmony_ci c->ohead_lnum = c->orph_first; 4648c2ecf20Sopenharmony_ci c->ohead_offs = 0; 4658c2ecf20Sopenharmony_ci } else { 4668c2ecf20Sopenharmony_ci /* 4678c2ecf20Sopenharmony_ci * We limit the number of orphans so that this should 4688c2ecf20Sopenharmony_ci * never happen. 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ci ubifs_err(c, "out of space in orphan area"); 4718c2ecf20Sopenharmony_ci err = -EINVAL; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 4748c2ecf20Sopenharmony_ci return err; 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci/** 4788c2ecf20Sopenharmony_ci * commit_orphans - commit orphans. 4798c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4808c2ecf20Sopenharmony_ci * 4818c2ecf20Sopenharmony_ci * This function commits orphans to flash. On success, %0 is returned, 4828c2ecf20Sopenharmony_ci * otherwise a negative error code is returned. 4838c2ecf20Sopenharmony_ci */ 4848c2ecf20Sopenharmony_cistatic int commit_orphans(struct ubifs_info *c) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci int avail, atomic = 0, err; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci ubifs_assert(c, c->cmt_orphans > 0); 4898c2ecf20Sopenharmony_ci avail = avail_orphs(c); 4908c2ecf20Sopenharmony_ci if (avail < c->cmt_orphans) { 4918c2ecf20Sopenharmony_ci /* Not enough space to write new orphans, so consolidate */ 4928c2ecf20Sopenharmony_ci err = consolidate(c); 4938c2ecf20Sopenharmony_ci if (err) 4948c2ecf20Sopenharmony_ci return err; 4958c2ecf20Sopenharmony_ci atomic = 1; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci err = write_orph_nodes(c, atomic); 4988c2ecf20Sopenharmony_ci return err; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci/** 5028c2ecf20Sopenharmony_ci * erase_deleted - erase the orphans marked for deletion. 5038c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 5048c2ecf20Sopenharmony_ci * 5058c2ecf20Sopenharmony_ci * During commit, the orphans being committed cannot be deleted, so they are 5068c2ecf20Sopenharmony_ci * marked for deletion and deleted by this function. Also, the recovery 5078c2ecf20Sopenharmony_ci * adds killed orphans to the deletion list, and therefore they are deleted 5088c2ecf20Sopenharmony_ci * here too. 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_cistatic void erase_deleted(struct ubifs_info *c) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, *dnext; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 5158c2ecf20Sopenharmony_ci dnext = c->orph_dnext; 5168c2ecf20Sopenharmony_ci while (dnext) { 5178c2ecf20Sopenharmony_ci orphan = dnext; 5188c2ecf20Sopenharmony_ci dnext = orphan->dnext; 5198c2ecf20Sopenharmony_ci ubifs_assert(c, !orphan->new); 5208c2ecf20Sopenharmony_ci ubifs_assert(c, orphan->del); 5218c2ecf20Sopenharmony_ci rb_erase(&orphan->rb, &c->orph_tree); 5228c2ecf20Sopenharmony_ci list_del(&orphan->list); 5238c2ecf20Sopenharmony_ci c->tot_orphans -= 1; 5248c2ecf20Sopenharmony_ci dbg_gen("deleting orphan ino %lu", (unsigned long)orphan->inum); 5258c2ecf20Sopenharmony_ci kfree(orphan); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci c->orph_dnext = NULL; 5288c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci/** 5328c2ecf20Sopenharmony_ci * ubifs_orphan_end_commit - end commit of orphans. 5338c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 5348c2ecf20Sopenharmony_ci * 5358c2ecf20Sopenharmony_ci * End commit of orphans. 5368c2ecf20Sopenharmony_ci */ 5378c2ecf20Sopenharmony_ciint ubifs_orphan_end_commit(struct ubifs_info *c) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci int err; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (c->cmt_orphans != 0) { 5428c2ecf20Sopenharmony_ci err = commit_orphans(c); 5438c2ecf20Sopenharmony_ci if (err) 5448c2ecf20Sopenharmony_ci return err; 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci erase_deleted(c); 5478c2ecf20Sopenharmony_ci err = dbg_check_orphans(c); 5488c2ecf20Sopenharmony_ci return err; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci/** 5528c2ecf20Sopenharmony_ci * ubifs_clear_orphans - erase all LEBs used for orphans. 5538c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 5548c2ecf20Sopenharmony_ci * 5558c2ecf20Sopenharmony_ci * If recovery is not required, then the orphans from the previous session 5568c2ecf20Sopenharmony_ci * are not needed. This function locates the LEBs used to record 5578c2ecf20Sopenharmony_ci * orphans, and un-maps them. 5588c2ecf20Sopenharmony_ci */ 5598c2ecf20Sopenharmony_ciint ubifs_clear_orphans(struct ubifs_info *c) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci int lnum, err; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { 5648c2ecf20Sopenharmony_ci err = ubifs_leb_unmap(c, lnum); 5658c2ecf20Sopenharmony_ci if (err) 5668c2ecf20Sopenharmony_ci return err; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci c->ohead_lnum = c->orph_first; 5698c2ecf20Sopenharmony_ci c->ohead_offs = 0; 5708c2ecf20Sopenharmony_ci return 0; 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci/** 5748c2ecf20Sopenharmony_ci * insert_dead_orphan - insert an orphan. 5758c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 5768c2ecf20Sopenharmony_ci * @inum: orphan inode number 5778c2ecf20Sopenharmony_ci * 5788c2ecf20Sopenharmony_ci * This function is a helper to the 'do_kill_orphans()' function. The orphan 5798c2ecf20Sopenharmony_ci * must be kept until the next commit, so it is added to the rb-tree and the 5808c2ecf20Sopenharmony_ci * deletion list. 5818c2ecf20Sopenharmony_ci */ 5828c2ecf20Sopenharmony_cistatic int insert_dead_orphan(struct ubifs_info *c, ino_t inum) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci struct ubifs_orphan *orphan, *o; 5858c2ecf20Sopenharmony_ci struct rb_node **p, *parent = NULL; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci orphan = kzalloc(sizeof(struct ubifs_orphan), GFP_KERNEL); 5888c2ecf20Sopenharmony_ci if (!orphan) 5898c2ecf20Sopenharmony_ci return -ENOMEM; 5908c2ecf20Sopenharmony_ci orphan->inum = inum; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci p = &c->orph_tree.rb_node; 5938c2ecf20Sopenharmony_ci while (*p) { 5948c2ecf20Sopenharmony_ci parent = *p; 5958c2ecf20Sopenharmony_ci o = rb_entry(parent, struct ubifs_orphan, rb); 5968c2ecf20Sopenharmony_ci if (inum < o->inum) 5978c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 5988c2ecf20Sopenharmony_ci else if (inum > o->inum) 5998c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 6008c2ecf20Sopenharmony_ci else { 6018c2ecf20Sopenharmony_ci /* Already added - no problem */ 6028c2ecf20Sopenharmony_ci kfree(orphan); 6038c2ecf20Sopenharmony_ci return 0; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci c->tot_orphans += 1; 6078c2ecf20Sopenharmony_ci rb_link_node(&orphan->rb, parent, p); 6088c2ecf20Sopenharmony_ci rb_insert_color(&orphan->rb, &c->orph_tree); 6098c2ecf20Sopenharmony_ci list_add_tail(&orphan->list, &c->orph_list); 6108c2ecf20Sopenharmony_ci orphan->del = 1; 6118c2ecf20Sopenharmony_ci orphan->dnext = c->orph_dnext; 6128c2ecf20Sopenharmony_ci c->orph_dnext = orphan; 6138c2ecf20Sopenharmony_ci dbg_mnt("ino %lu, new %d, tot %d", (unsigned long)inum, 6148c2ecf20Sopenharmony_ci c->new_orphans, c->tot_orphans); 6158c2ecf20Sopenharmony_ci return 0; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci/** 6198c2ecf20Sopenharmony_ci * do_kill_orphans - remove orphan inodes from the index. 6208c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 6218c2ecf20Sopenharmony_ci * @sleb: scanned LEB 6228c2ecf20Sopenharmony_ci * @last_cmt_no: cmt_no of last orphan node read is passed and returned here 6238c2ecf20Sopenharmony_ci * @outofdate: whether the LEB is out of date is returned here 6248c2ecf20Sopenharmony_ci * @last_flagged: whether the end orphan node is encountered 6258c2ecf20Sopenharmony_ci * 6268c2ecf20Sopenharmony_ci * This function is a helper to the 'kill_orphans()' function. It goes through 6278c2ecf20Sopenharmony_ci * every orphan node in a LEB and for every inode number recorded, removes 6288c2ecf20Sopenharmony_ci * all keys for that inode from the TNC. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_cistatic int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, 6318c2ecf20Sopenharmony_ci unsigned long long *last_cmt_no, int *outofdate, 6328c2ecf20Sopenharmony_ci int *last_flagged) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 6358c2ecf20Sopenharmony_ci struct ubifs_orph_node *orph; 6368c2ecf20Sopenharmony_ci struct ubifs_ino_node *ino = NULL; 6378c2ecf20Sopenharmony_ci unsigned long long cmt_no; 6388c2ecf20Sopenharmony_ci ino_t inum; 6398c2ecf20Sopenharmony_ci int i, n, err, first = 1; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); 6428c2ecf20Sopenharmony_ci if (!ino) 6438c2ecf20Sopenharmony_ci return -ENOMEM; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci list_for_each_entry(snod, &sleb->nodes, list) { 6468c2ecf20Sopenharmony_ci if (snod->type != UBIFS_ORPH_NODE) { 6478c2ecf20Sopenharmony_ci ubifs_err(c, "invalid node type %d in orphan area at %d:%d", 6488c2ecf20Sopenharmony_ci snod->type, sleb->lnum, snod->offs); 6498c2ecf20Sopenharmony_ci ubifs_dump_node(c, snod->node, 6508c2ecf20Sopenharmony_ci c->leb_size - snod->offs); 6518c2ecf20Sopenharmony_ci err = -EINVAL; 6528c2ecf20Sopenharmony_ci goto out_free; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci orph = snod->node; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Check commit number */ 6588c2ecf20Sopenharmony_ci cmt_no = le64_to_cpu(orph->cmt_no) & LLONG_MAX; 6598c2ecf20Sopenharmony_ci /* 6608c2ecf20Sopenharmony_ci * The commit number on the master node may be less, because 6618c2ecf20Sopenharmony_ci * of a failed commit. If there are several failed commits in a 6628c2ecf20Sopenharmony_ci * row, the commit number written on orphan nodes will continue 6638c2ecf20Sopenharmony_ci * to increase (because the commit number is adjusted here) even 6648c2ecf20Sopenharmony_ci * though the commit number on the master node stays the same 6658c2ecf20Sopenharmony_ci * because the master node has not been re-written. 6668c2ecf20Sopenharmony_ci */ 6678c2ecf20Sopenharmony_ci if (cmt_no > c->cmt_no) 6688c2ecf20Sopenharmony_ci c->cmt_no = cmt_no; 6698c2ecf20Sopenharmony_ci if (cmt_no < *last_cmt_no && *last_flagged) { 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * The last orphan node had a higher commit number and 6728c2ecf20Sopenharmony_ci * was flagged as the last written for that commit 6738c2ecf20Sopenharmony_ci * number. That makes this orphan node, out of date. 6748c2ecf20Sopenharmony_ci */ 6758c2ecf20Sopenharmony_ci if (!first) { 6768c2ecf20Sopenharmony_ci ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d", 6778c2ecf20Sopenharmony_ci cmt_no, sleb->lnum, snod->offs); 6788c2ecf20Sopenharmony_ci ubifs_dump_node(c, snod->node, 6798c2ecf20Sopenharmony_ci c->leb_size - snod->offs); 6808c2ecf20Sopenharmony_ci err = -EINVAL; 6818c2ecf20Sopenharmony_ci goto out_free; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci dbg_rcvry("out of date LEB %d", sleb->lnum); 6848c2ecf20Sopenharmony_ci *outofdate = 1; 6858c2ecf20Sopenharmony_ci err = 0; 6868c2ecf20Sopenharmony_ci goto out_free; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (first) 6908c2ecf20Sopenharmony_ci first = 0; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; 6938c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 6948c2ecf20Sopenharmony_ci union ubifs_key key1, key2; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci inum = le64_to_cpu(orph->inos[i]); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci ino_key_init(c, &key1, inum); 6998c2ecf20Sopenharmony_ci err = ubifs_tnc_lookup(c, &key1, ino); 7008c2ecf20Sopenharmony_ci if (err && err != -ENOENT) 7018c2ecf20Sopenharmony_ci goto out_free; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* 7048c2ecf20Sopenharmony_ci * Check whether an inode can really get deleted. 7058c2ecf20Sopenharmony_ci * linkat() with O_TMPFILE allows rebirth of an inode. 7068c2ecf20Sopenharmony_ci */ 7078c2ecf20Sopenharmony_ci if (err == 0 && ino->nlink == 0) { 7088c2ecf20Sopenharmony_ci dbg_rcvry("deleting orphaned inode %lu", 7098c2ecf20Sopenharmony_ci (unsigned long)inum); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci lowest_ino_key(c, &key1, inum); 7128c2ecf20Sopenharmony_ci highest_ino_key(c, &key2, inum); 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci err = ubifs_tnc_remove_range(c, &key1, &key2); 7158c2ecf20Sopenharmony_ci if (err) 7168c2ecf20Sopenharmony_ci goto out_ro; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci err = insert_dead_orphan(c, inum); 7208c2ecf20Sopenharmony_ci if (err) 7218c2ecf20Sopenharmony_ci goto out_free; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci *last_cmt_no = cmt_no; 7258c2ecf20Sopenharmony_ci if (le64_to_cpu(orph->cmt_no) & (1ULL << 63)) { 7268c2ecf20Sopenharmony_ci dbg_rcvry("last orph node for commit %llu at %d:%d", 7278c2ecf20Sopenharmony_ci cmt_no, sleb->lnum, snod->offs); 7288c2ecf20Sopenharmony_ci *last_flagged = 1; 7298c2ecf20Sopenharmony_ci } else 7308c2ecf20Sopenharmony_ci *last_flagged = 0; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci err = 0; 7348c2ecf20Sopenharmony_ciout_free: 7358c2ecf20Sopenharmony_ci kfree(ino); 7368c2ecf20Sopenharmony_ci return err; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ciout_ro: 7398c2ecf20Sopenharmony_ci ubifs_ro_mode(c, err); 7408c2ecf20Sopenharmony_ci kfree(ino); 7418c2ecf20Sopenharmony_ci return err; 7428c2ecf20Sopenharmony_ci} 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci/** 7458c2ecf20Sopenharmony_ci * kill_orphans - remove all orphan inodes from the index. 7468c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 7478c2ecf20Sopenharmony_ci * 7488c2ecf20Sopenharmony_ci * If recovery is required, then orphan inodes recorded during the previous 7498c2ecf20Sopenharmony_ci * session (which ended with an unclean unmount) must be deleted from the index. 7508c2ecf20Sopenharmony_ci * This is done by updating the TNC, but since the index is not updated until 7518c2ecf20Sopenharmony_ci * the next commit, the LEBs where the orphan information is recorded are not 7528c2ecf20Sopenharmony_ci * erased until the next commit. 7538c2ecf20Sopenharmony_ci */ 7548c2ecf20Sopenharmony_cistatic int kill_orphans(struct ubifs_info *c) 7558c2ecf20Sopenharmony_ci{ 7568c2ecf20Sopenharmony_ci unsigned long long last_cmt_no = 0; 7578c2ecf20Sopenharmony_ci int lnum, err = 0, outofdate = 0, last_flagged = 0; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci c->ohead_lnum = c->orph_first; 7608c2ecf20Sopenharmony_ci c->ohead_offs = 0; 7618c2ecf20Sopenharmony_ci /* Check no-orphans flag and skip this if no orphans */ 7628c2ecf20Sopenharmony_ci if (c->no_orphs) { 7638c2ecf20Sopenharmony_ci dbg_rcvry("no orphans"); 7648c2ecf20Sopenharmony_ci return 0; 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci /* 7678c2ecf20Sopenharmony_ci * Orph nodes always start at c->orph_first and are written to each 7688c2ecf20Sopenharmony_ci * successive LEB in turn. Generally unused LEBs will have been unmapped 7698c2ecf20Sopenharmony_ci * but may contain out of date orphan nodes if the unmap didn't go 7708c2ecf20Sopenharmony_ci * through. In addition, the last orphan node written for each commit is 7718c2ecf20Sopenharmony_ci * marked (top bit of orph->cmt_no is set to 1). It is possible that 7728c2ecf20Sopenharmony_ci * there are orphan nodes from the next commit (i.e. the commit did not 7738c2ecf20Sopenharmony_ci * complete successfully). In that case, no orphans will have been lost 7748c2ecf20Sopenharmony_ci * due to the way that orphans are written, and any orphans added will 7758c2ecf20Sopenharmony_ci * be valid orphans anyway and so can be deleted. 7768c2ecf20Sopenharmony_ci */ 7778c2ecf20Sopenharmony_ci for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { 7788c2ecf20Sopenharmony_ci struct ubifs_scan_leb *sleb; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci dbg_rcvry("LEB %d", lnum); 7818c2ecf20Sopenharmony_ci sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1); 7828c2ecf20Sopenharmony_ci if (IS_ERR(sleb)) { 7838c2ecf20Sopenharmony_ci if (PTR_ERR(sleb) == -EUCLEAN) 7848c2ecf20Sopenharmony_ci sleb = ubifs_recover_leb(c, lnum, 0, 7858c2ecf20Sopenharmony_ci c->sbuf, -1); 7868c2ecf20Sopenharmony_ci if (IS_ERR(sleb)) { 7878c2ecf20Sopenharmony_ci err = PTR_ERR(sleb); 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci err = do_kill_orphans(c, sleb, &last_cmt_no, &outofdate, 7928c2ecf20Sopenharmony_ci &last_flagged); 7938c2ecf20Sopenharmony_ci if (err || outofdate) { 7948c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci if (sleb->endpt) { 7988c2ecf20Sopenharmony_ci c->ohead_lnum = lnum; 7998c2ecf20Sopenharmony_ci c->ohead_offs = sleb->endpt; 8008c2ecf20Sopenharmony_ci } 8018c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci return err; 8048c2ecf20Sopenharmony_ci} 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci/** 8078c2ecf20Sopenharmony_ci * ubifs_mount_orphans - delete orphan inodes and erase LEBs that recorded them. 8088c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 8098c2ecf20Sopenharmony_ci * @unclean: indicates recovery from unclean unmount 8108c2ecf20Sopenharmony_ci * @read_only: indicates read only mount 8118c2ecf20Sopenharmony_ci * 8128c2ecf20Sopenharmony_ci * This function is called when mounting to erase orphans from the previous 8138c2ecf20Sopenharmony_ci * session. If UBIFS was not unmounted cleanly, then the inodes recorded as 8148c2ecf20Sopenharmony_ci * orphans are deleted. 8158c2ecf20Sopenharmony_ci */ 8168c2ecf20Sopenharmony_ciint ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci int err = 0; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci c->max_orphans = tot_avail_orphs(c); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci if (!read_only) { 8238c2ecf20Sopenharmony_ci c->orph_buf = vmalloc(c->leb_size); 8248c2ecf20Sopenharmony_ci if (!c->orph_buf) 8258c2ecf20Sopenharmony_ci return -ENOMEM; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci if (unclean) 8298c2ecf20Sopenharmony_ci err = kill_orphans(c); 8308c2ecf20Sopenharmony_ci else if (!read_only) 8318c2ecf20Sopenharmony_ci err = ubifs_clear_orphans(c); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci return err; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci/* 8378c2ecf20Sopenharmony_ci * Everything below is related to debugging. 8388c2ecf20Sopenharmony_ci */ 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_cistruct check_orphan { 8418c2ecf20Sopenharmony_ci struct rb_node rb; 8428c2ecf20Sopenharmony_ci ino_t inum; 8438c2ecf20Sopenharmony_ci}; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistruct check_info { 8468c2ecf20Sopenharmony_ci unsigned long last_ino; 8478c2ecf20Sopenharmony_ci unsigned long tot_inos; 8488c2ecf20Sopenharmony_ci unsigned long missing; 8498c2ecf20Sopenharmony_ci unsigned long long leaf_cnt; 8508c2ecf20Sopenharmony_ci struct ubifs_ino_node *node; 8518c2ecf20Sopenharmony_ci struct rb_root root; 8528c2ecf20Sopenharmony_ci}; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_cistatic bool dbg_find_orphan(struct ubifs_info *c, ino_t inum) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci bool found = false; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci spin_lock(&c->orphan_lock); 8598c2ecf20Sopenharmony_ci found = !!lookup_orphan(c, inum); 8608c2ecf20Sopenharmony_ci spin_unlock(&c->orphan_lock); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return found; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_cistatic int dbg_ins_check_orphan(struct rb_root *root, ino_t inum) 8668c2ecf20Sopenharmony_ci{ 8678c2ecf20Sopenharmony_ci struct check_orphan *orphan, *o; 8688c2ecf20Sopenharmony_ci struct rb_node **p, *parent = NULL; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci orphan = kzalloc(sizeof(struct check_orphan), GFP_NOFS); 8718c2ecf20Sopenharmony_ci if (!orphan) 8728c2ecf20Sopenharmony_ci return -ENOMEM; 8738c2ecf20Sopenharmony_ci orphan->inum = inum; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci p = &root->rb_node; 8768c2ecf20Sopenharmony_ci while (*p) { 8778c2ecf20Sopenharmony_ci parent = *p; 8788c2ecf20Sopenharmony_ci o = rb_entry(parent, struct check_orphan, rb); 8798c2ecf20Sopenharmony_ci if (inum < o->inum) 8808c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 8818c2ecf20Sopenharmony_ci else if (inum > o->inum) 8828c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 8838c2ecf20Sopenharmony_ci else { 8848c2ecf20Sopenharmony_ci kfree(orphan); 8858c2ecf20Sopenharmony_ci return 0; 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci rb_link_node(&orphan->rb, parent, p); 8898c2ecf20Sopenharmony_ci rb_insert_color(&orphan->rb, root); 8908c2ecf20Sopenharmony_ci return 0; 8918c2ecf20Sopenharmony_ci} 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_cistatic int dbg_find_check_orphan(struct rb_root *root, ino_t inum) 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci struct check_orphan *o; 8968c2ecf20Sopenharmony_ci struct rb_node *p; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci p = root->rb_node; 8998c2ecf20Sopenharmony_ci while (p) { 9008c2ecf20Sopenharmony_ci o = rb_entry(p, struct check_orphan, rb); 9018c2ecf20Sopenharmony_ci if (inum < o->inum) 9028c2ecf20Sopenharmony_ci p = p->rb_left; 9038c2ecf20Sopenharmony_ci else if (inum > o->inum) 9048c2ecf20Sopenharmony_ci p = p->rb_right; 9058c2ecf20Sopenharmony_ci else 9068c2ecf20Sopenharmony_ci return 1; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci return 0; 9098c2ecf20Sopenharmony_ci} 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_cistatic void dbg_free_check_tree(struct rb_root *root) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci struct check_orphan *o, *n; 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(o, n, root, rb) 9168c2ecf20Sopenharmony_ci kfree(o); 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, 9208c2ecf20Sopenharmony_ci void *priv) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci struct check_info *ci = priv; 9238c2ecf20Sopenharmony_ci ino_t inum; 9248c2ecf20Sopenharmony_ci int err; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci inum = key_inum(c, &zbr->key); 9278c2ecf20Sopenharmony_ci if (inum != ci->last_ino) { 9288c2ecf20Sopenharmony_ci /* Lowest node type is the inode node, so it comes first */ 9298c2ecf20Sopenharmony_ci if (key_type(c, &zbr->key) != UBIFS_INO_KEY) 9308c2ecf20Sopenharmony_ci ubifs_err(c, "found orphan node ino %lu, type %d", 9318c2ecf20Sopenharmony_ci (unsigned long)inum, key_type(c, &zbr->key)); 9328c2ecf20Sopenharmony_ci ci->last_ino = inum; 9338c2ecf20Sopenharmony_ci ci->tot_inos += 1; 9348c2ecf20Sopenharmony_ci err = ubifs_tnc_read_node(c, zbr, ci->node); 9358c2ecf20Sopenharmony_ci if (err) { 9368c2ecf20Sopenharmony_ci ubifs_err(c, "node read failed, error %d", err); 9378c2ecf20Sopenharmony_ci return err; 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci if (ci->node->nlink == 0) 9408c2ecf20Sopenharmony_ci /* Must be recorded as an orphan */ 9418c2ecf20Sopenharmony_ci if (!dbg_find_check_orphan(&ci->root, inum) && 9428c2ecf20Sopenharmony_ci !dbg_find_orphan(c, inum)) { 9438c2ecf20Sopenharmony_ci ubifs_err(c, "missing orphan, ino %lu", 9448c2ecf20Sopenharmony_ci (unsigned long)inum); 9458c2ecf20Sopenharmony_ci ci->missing += 1; 9468c2ecf20Sopenharmony_ci } 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci ci->leaf_cnt += 1; 9498c2ecf20Sopenharmony_ci return 0; 9508c2ecf20Sopenharmony_ci} 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_cistatic int dbg_read_orphans(struct check_info *ci, struct ubifs_scan_leb *sleb) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 9558c2ecf20Sopenharmony_ci struct ubifs_orph_node *orph; 9568c2ecf20Sopenharmony_ci ino_t inum; 9578c2ecf20Sopenharmony_ci int i, n, err; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci list_for_each_entry(snod, &sleb->nodes, list) { 9608c2ecf20Sopenharmony_ci cond_resched(); 9618c2ecf20Sopenharmony_ci if (snod->type != UBIFS_ORPH_NODE) 9628c2ecf20Sopenharmony_ci continue; 9638c2ecf20Sopenharmony_ci orph = snod->node; 9648c2ecf20Sopenharmony_ci n = (le32_to_cpu(orph->ch.len) - UBIFS_ORPH_NODE_SZ) >> 3; 9658c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 9668c2ecf20Sopenharmony_ci inum = le64_to_cpu(orph->inos[i]); 9678c2ecf20Sopenharmony_ci err = dbg_ins_check_orphan(&ci->root, inum); 9688c2ecf20Sopenharmony_ci if (err) 9698c2ecf20Sopenharmony_ci return err; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci return 0; 9738c2ecf20Sopenharmony_ci} 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_cistatic int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci) 9768c2ecf20Sopenharmony_ci{ 9778c2ecf20Sopenharmony_ci int lnum, err = 0; 9788c2ecf20Sopenharmony_ci void *buf; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci /* Check no-orphans flag and skip this if no orphans */ 9818c2ecf20Sopenharmony_ci if (c->no_orphs) 9828c2ecf20Sopenharmony_ci return 0; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci buf = __vmalloc(c->leb_size, GFP_NOFS); 9858c2ecf20Sopenharmony_ci if (!buf) { 9868c2ecf20Sopenharmony_ci ubifs_err(c, "cannot allocate memory to check orphans"); 9878c2ecf20Sopenharmony_ci return 0; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) { 9918c2ecf20Sopenharmony_ci struct ubifs_scan_leb *sleb; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci sleb = ubifs_scan(c, lnum, 0, buf, 0); 9948c2ecf20Sopenharmony_ci if (IS_ERR(sleb)) { 9958c2ecf20Sopenharmony_ci err = PTR_ERR(sleb); 9968c2ecf20Sopenharmony_ci break; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci err = dbg_read_orphans(ci, sleb); 10008c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 10018c2ecf20Sopenharmony_ci if (err) 10028c2ecf20Sopenharmony_ci break; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci vfree(buf); 10068c2ecf20Sopenharmony_ci return err; 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic int dbg_check_orphans(struct ubifs_info *c) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci struct check_info ci; 10128c2ecf20Sopenharmony_ci int err; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci if (!dbg_is_chk_orph(c)) 10158c2ecf20Sopenharmony_ci return 0; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci ci.last_ino = 0; 10188c2ecf20Sopenharmony_ci ci.tot_inos = 0; 10198c2ecf20Sopenharmony_ci ci.missing = 0; 10208c2ecf20Sopenharmony_ci ci.leaf_cnt = 0; 10218c2ecf20Sopenharmony_ci ci.root = RB_ROOT; 10228c2ecf20Sopenharmony_ci ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS); 10238c2ecf20Sopenharmony_ci if (!ci.node) { 10248c2ecf20Sopenharmony_ci ubifs_err(c, "out of memory"); 10258c2ecf20Sopenharmony_ci return -ENOMEM; 10268c2ecf20Sopenharmony_ci } 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci err = dbg_scan_orphans(c, &ci); 10298c2ecf20Sopenharmony_ci if (err) 10308c2ecf20Sopenharmony_ci goto out; 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci); 10338c2ecf20Sopenharmony_ci if (err) { 10348c2ecf20Sopenharmony_ci ubifs_err(c, "cannot scan TNC, error %d", err); 10358c2ecf20Sopenharmony_ci goto out; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci if (ci.missing) { 10398c2ecf20Sopenharmony_ci ubifs_err(c, "%lu missing orphan(s)", ci.missing); 10408c2ecf20Sopenharmony_ci err = -EINVAL; 10418c2ecf20Sopenharmony_ci goto out; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci dbg_cmt("last inode number is %lu", ci.last_ino); 10458c2ecf20Sopenharmony_ci dbg_cmt("total number of inodes is %lu", ci.tot_inos); 10468c2ecf20Sopenharmony_ci dbg_cmt("total number of leaf nodes is %llu", ci.leaf_cnt); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ciout: 10498c2ecf20Sopenharmony_ci dbg_free_check_tree(&ci.root); 10508c2ecf20Sopenharmony_ci kfree(ci.node); 10518c2ecf20Sopenharmony_ci return err; 10528c2ecf20Sopenharmony_ci} 1053