xref: /kernel/linux/linux-5.10/fs/ubifs/orphan.c (revision 8c2ecf20)
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