xref: /kernel/linux/linux-6.6/fs/ubifs/tnc_misc.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file is part of UBIFS.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors: Adrian Hunter
862306a36Sopenharmony_ci *          Artem Bityutskiy (Битюцкий Артём)
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * This file contains miscelanious TNC-related functions shared betweend
1362306a36Sopenharmony_ci * different files. This file does not form any logically separate TNC
1462306a36Sopenharmony_ci * sub-system. The file was created because there is a lot of TNC code and
1562306a36Sopenharmony_ci * putting it all in one file would make that file too big and unreadable.
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "ubifs.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/**
2162306a36Sopenharmony_ci * ubifs_tnc_levelorder_next - next TNC tree element in levelorder traversal.
2262306a36Sopenharmony_ci * @c: UBIFS file-system description object
2362306a36Sopenharmony_ci * @zr: root of the subtree to traverse
2462306a36Sopenharmony_ci * @znode: previous znode
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * This function implements levelorder TNC traversal. The LNC is ignored.
2762306a36Sopenharmony_ci * Returns the next element or %NULL if @znode is already the last one.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_cistruct ubifs_znode *ubifs_tnc_levelorder_next(const struct ubifs_info *c,
3062306a36Sopenharmony_ci					      struct ubifs_znode *zr,
3162306a36Sopenharmony_ci					      struct ubifs_znode *znode)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	int level, iip, level_search = 0;
3462306a36Sopenharmony_ci	struct ubifs_znode *zn;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	ubifs_assert(c, zr);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (unlikely(!znode))
3962306a36Sopenharmony_ci		return zr;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (unlikely(znode == zr)) {
4262306a36Sopenharmony_ci		if (znode->level == 0)
4362306a36Sopenharmony_ci			return NULL;
4462306a36Sopenharmony_ci		return ubifs_tnc_find_child(zr, 0);
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	level = znode->level;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	iip = znode->iip;
5062306a36Sopenharmony_ci	while (1) {
5162306a36Sopenharmony_ci		ubifs_assert(c, znode->level <= zr->level);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		/*
5462306a36Sopenharmony_ci		 * First walk up until there is a znode with next branch to
5562306a36Sopenharmony_ci		 * look at.
5662306a36Sopenharmony_ci		 */
5762306a36Sopenharmony_ci		while (znode->parent != zr && iip >= znode->parent->child_cnt) {
5862306a36Sopenharmony_ci			znode = znode->parent;
5962306a36Sopenharmony_ci			iip = znode->iip;
6062306a36Sopenharmony_ci		}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci		if (unlikely(znode->parent == zr &&
6362306a36Sopenharmony_ci			     iip >= znode->parent->child_cnt)) {
6462306a36Sopenharmony_ci			/* This level is done, switch to the lower one */
6562306a36Sopenharmony_ci			level -= 1;
6662306a36Sopenharmony_ci			if (level_search || level < 0)
6762306a36Sopenharmony_ci				/*
6862306a36Sopenharmony_ci				 * We were already looking for znode at lower
6962306a36Sopenharmony_ci				 * level ('level_search'). As we are here
7062306a36Sopenharmony_ci				 * again, it just does not exist. Or all levels
7162306a36Sopenharmony_ci				 * were finished ('level < 0').
7262306a36Sopenharmony_ci				 */
7362306a36Sopenharmony_ci				return NULL;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci			level_search = 1;
7662306a36Sopenharmony_ci			iip = -1;
7762306a36Sopenharmony_ci			znode = ubifs_tnc_find_child(zr, 0);
7862306a36Sopenharmony_ci			ubifs_assert(c, znode);
7962306a36Sopenharmony_ci		}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		/* Switch to the next index */
8262306a36Sopenharmony_ci		zn = ubifs_tnc_find_child(znode->parent, iip + 1);
8362306a36Sopenharmony_ci		if (!zn) {
8462306a36Sopenharmony_ci			/* No more children to look at, we have walk up */
8562306a36Sopenharmony_ci			iip = znode->parent->child_cnt;
8662306a36Sopenharmony_ci			continue;
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci		/* Walk back down to the level we came from ('level') */
9062306a36Sopenharmony_ci		while (zn->level != level) {
9162306a36Sopenharmony_ci			znode = zn;
9262306a36Sopenharmony_ci			zn = ubifs_tnc_find_child(zn, 0);
9362306a36Sopenharmony_ci			if (!zn) {
9462306a36Sopenharmony_ci				/*
9562306a36Sopenharmony_ci				 * This path is not too deep so it does not
9662306a36Sopenharmony_ci				 * reach 'level'. Try next path.
9762306a36Sopenharmony_ci				 */
9862306a36Sopenharmony_ci				iip = znode->iip;
9962306a36Sopenharmony_ci				break;
10062306a36Sopenharmony_ci			}
10162306a36Sopenharmony_ci		}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		if (zn) {
10462306a36Sopenharmony_ci			ubifs_assert(c, zn->level >= 0);
10562306a36Sopenharmony_ci			return zn;
10662306a36Sopenharmony_ci		}
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/**
11162306a36Sopenharmony_ci * ubifs_search_zbranch - search znode branch.
11262306a36Sopenharmony_ci * @c: UBIFS file-system description object
11362306a36Sopenharmony_ci * @znode: znode to search in
11462306a36Sopenharmony_ci * @key: key to search for
11562306a36Sopenharmony_ci * @n: znode branch slot number is returned here
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci * This is a helper function which search branch with key @key in @znode using
11862306a36Sopenharmony_ci * binary search. The result of the search may be:
11962306a36Sopenharmony_ci *   o exact match, then %1 is returned, and the slot number of the branch is
12062306a36Sopenharmony_ci *     stored in @n;
12162306a36Sopenharmony_ci *   o no exact match, then %0 is returned and the slot number of the left
12262306a36Sopenharmony_ci *     closest branch is returned in @n; the slot if all keys in this znode are
12362306a36Sopenharmony_ci *     greater than @key, then %-1 is returned in @n.
12462306a36Sopenharmony_ci */
12562306a36Sopenharmony_ciint ubifs_search_zbranch(const struct ubifs_info *c,
12662306a36Sopenharmony_ci			 const struct ubifs_znode *znode,
12762306a36Sopenharmony_ci			 const union ubifs_key *key, int *n)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	int beg = 0, end = znode->child_cnt, mid;
13062306a36Sopenharmony_ci	int cmp;
13162306a36Sopenharmony_ci	const struct ubifs_zbranch *zbr = &znode->zbranch[0];
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	ubifs_assert(c, end > beg);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	while (end > beg) {
13662306a36Sopenharmony_ci		mid = (beg + end) >> 1;
13762306a36Sopenharmony_ci		cmp = keys_cmp(c, key, &zbr[mid].key);
13862306a36Sopenharmony_ci		if (cmp > 0)
13962306a36Sopenharmony_ci			beg = mid + 1;
14062306a36Sopenharmony_ci		else if (cmp < 0)
14162306a36Sopenharmony_ci			end = mid;
14262306a36Sopenharmony_ci		else {
14362306a36Sopenharmony_ci			*n = mid;
14462306a36Sopenharmony_ci			return 1;
14562306a36Sopenharmony_ci		}
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	*n = end - 1;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/* The insert point is after *n */
15162306a36Sopenharmony_ci	ubifs_assert(c, *n >= -1 && *n < znode->child_cnt);
15262306a36Sopenharmony_ci	if (*n == -1)
15362306a36Sopenharmony_ci		ubifs_assert(c, keys_cmp(c, key, &zbr[0].key) < 0);
15462306a36Sopenharmony_ci	else
15562306a36Sopenharmony_ci		ubifs_assert(c, keys_cmp(c, key, &zbr[*n].key) > 0);
15662306a36Sopenharmony_ci	if (*n + 1 < znode->child_cnt)
15762306a36Sopenharmony_ci		ubifs_assert(c, keys_cmp(c, key, &zbr[*n + 1].key) < 0);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	return 0;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/**
16362306a36Sopenharmony_ci * ubifs_tnc_postorder_first - find first znode to do postorder tree traversal.
16462306a36Sopenharmony_ci * @znode: znode to start at (root of the sub-tree to traverse)
16562306a36Sopenharmony_ci *
16662306a36Sopenharmony_ci * Find the lowest leftmost znode in a subtree of the TNC tree. The LNC is
16762306a36Sopenharmony_ci * ignored.
16862306a36Sopenharmony_ci */
16962306a36Sopenharmony_cistruct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	if (unlikely(!znode))
17262306a36Sopenharmony_ci		return NULL;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	while (znode->level > 0) {
17562306a36Sopenharmony_ci		struct ubifs_znode *child;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci		child = ubifs_tnc_find_child(znode, 0);
17862306a36Sopenharmony_ci		if (!child)
17962306a36Sopenharmony_ci			return znode;
18062306a36Sopenharmony_ci		znode = child;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	return znode;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/**
18762306a36Sopenharmony_ci * ubifs_tnc_postorder_next - next TNC tree element in postorder traversal.
18862306a36Sopenharmony_ci * @c: UBIFS file-system description object
18962306a36Sopenharmony_ci * @znode: previous znode
19062306a36Sopenharmony_ci *
19162306a36Sopenharmony_ci * This function implements postorder TNC traversal. The LNC is ignored.
19262306a36Sopenharmony_ci * Returns the next element or %NULL if @znode is already the last one.
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_cistruct ubifs_znode *ubifs_tnc_postorder_next(const struct ubifs_info *c,
19562306a36Sopenharmony_ci					     struct ubifs_znode *znode)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	struct ubifs_znode *zn;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	ubifs_assert(c, znode);
20062306a36Sopenharmony_ci	if (unlikely(!znode->parent))
20162306a36Sopenharmony_ci		return NULL;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	/* Switch to the next index in the parent */
20462306a36Sopenharmony_ci	zn = ubifs_tnc_find_child(znode->parent, znode->iip + 1);
20562306a36Sopenharmony_ci	if (!zn)
20662306a36Sopenharmony_ci		/* This is in fact the last child, return parent */
20762306a36Sopenharmony_ci		return znode->parent;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	/* Go to the first znode in this new subtree */
21062306a36Sopenharmony_ci	return ubifs_tnc_postorder_first(zn);
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/**
21462306a36Sopenharmony_ci * ubifs_destroy_tnc_subtree - destroy all znodes connected to a subtree.
21562306a36Sopenharmony_ci * @c: UBIFS file-system description object
21662306a36Sopenharmony_ci * @znode: znode defining subtree to destroy
21762306a36Sopenharmony_ci *
21862306a36Sopenharmony_ci * This function destroys subtree of the TNC tree. Returns number of clean
21962306a36Sopenharmony_ci * znodes in the subtree.
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_cilong ubifs_destroy_tnc_subtree(const struct ubifs_info *c,
22262306a36Sopenharmony_ci			       struct ubifs_znode *znode)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct ubifs_znode *zn = ubifs_tnc_postorder_first(znode);
22562306a36Sopenharmony_ci	long clean_freed = 0;
22662306a36Sopenharmony_ci	int n;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	ubifs_assert(c, zn);
22962306a36Sopenharmony_ci	while (1) {
23062306a36Sopenharmony_ci		for (n = 0; n < zn->child_cnt; n++) {
23162306a36Sopenharmony_ci			if (!zn->zbranch[n].znode)
23262306a36Sopenharmony_ci				continue;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci			if (zn->level > 0 &&
23562306a36Sopenharmony_ci			    !ubifs_zn_dirty(zn->zbranch[n].znode))
23662306a36Sopenharmony_ci				clean_freed += 1;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci			cond_resched();
23962306a36Sopenharmony_ci			kfree(zn->zbranch[n].znode);
24062306a36Sopenharmony_ci		}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci		if (zn == znode) {
24362306a36Sopenharmony_ci			if (!ubifs_zn_dirty(zn))
24462306a36Sopenharmony_ci				clean_freed += 1;
24562306a36Sopenharmony_ci			kfree(zn);
24662306a36Sopenharmony_ci			return clean_freed;
24762306a36Sopenharmony_ci		}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci		zn = ubifs_tnc_postorder_next(c, zn);
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci/**
25462306a36Sopenharmony_ci * read_znode - read an indexing node from flash and fill znode.
25562306a36Sopenharmony_ci * @c: UBIFS file-system description object
25662306a36Sopenharmony_ci * @zzbr: the zbranch describing the node to read
25762306a36Sopenharmony_ci * @znode: znode to read to
25862306a36Sopenharmony_ci *
25962306a36Sopenharmony_ci * This function reads an indexing node from the flash media and fills znode
26062306a36Sopenharmony_ci * with the read data. Returns zero in case of success and a negative error
26162306a36Sopenharmony_ci * code in case of failure. The read indexing node is validated and if anything
26262306a36Sopenharmony_ci * is wrong with it, this function prints complaint messages and returns
26362306a36Sopenharmony_ci * %-EINVAL.
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_cistatic int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr,
26662306a36Sopenharmony_ci		      struct ubifs_znode *znode)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	int lnum = zzbr->lnum;
26962306a36Sopenharmony_ci	int offs = zzbr->offs;
27062306a36Sopenharmony_ci	int len = zzbr->len;
27162306a36Sopenharmony_ci	int i, err, type, cmp;
27262306a36Sopenharmony_ci	struct ubifs_idx_node *idx;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
27562306a36Sopenharmony_ci	if (!idx)
27662306a36Sopenharmony_ci		return -ENOMEM;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
27962306a36Sopenharmony_ci	if (err < 0) {
28062306a36Sopenharmony_ci		kfree(idx);
28162306a36Sopenharmony_ci		return err;
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	err = ubifs_node_check_hash(c, idx, zzbr->hash);
28562306a36Sopenharmony_ci	if (err) {
28662306a36Sopenharmony_ci		ubifs_bad_hash(c, idx, zzbr->hash, lnum, offs);
28762306a36Sopenharmony_ci		kfree(idx);
28862306a36Sopenharmony_ci		return err;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	znode->child_cnt = le16_to_cpu(idx->child_cnt);
29262306a36Sopenharmony_ci	znode->level = le16_to_cpu(idx->level);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	dbg_tnc("LEB %d:%d, level %d, %d branch",
29562306a36Sopenharmony_ci		lnum, offs, znode->level, znode->child_cnt);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
29862306a36Sopenharmony_ci		ubifs_err(c, "current fanout %d, branch count %d",
29962306a36Sopenharmony_ci			  c->fanout, znode->child_cnt);
30062306a36Sopenharmony_ci		ubifs_err(c, "max levels %d, znode level %d",
30162306a36Sopenharmony_ci			  UBIFS_MAX_LEVELS, znode->level);
30262306a36Sopenharmony_ci		err = 1;
30362306a36Sopenharmony_ci		goto out_dump;
30462306a36Sopenharmony_ci	}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	for (i = 0; i < znode->child_cnt; i++) {
30762306a36Sopenharmony_ci		struct ubifs_branch *br = ubifs_idx_branch(c, idx, i);
30862306a36Sopenharmony_ci		struct ubifs_zbranch *zbr = &znode->zbranch[i];
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		key_read(c, &br->key, &zbr->key);
31162306a36Sopenharmony_ci		zbr->lnum = le32_to_cpu(br->lnum);
31262306a36Sopenharmony_ci		zbr->offs = le32_to_cpu(br->offs);
31362306a36Sopenharmony_ci		zbr->len  = le32_to_cpu(br->len);
31462306a36Sopenharmony_ci		ubifs_copy_hash(c, ubifs_branch_hash(c, br), zbr->hash);
31562306a36Sopenharmony_ci		zbr->znode = NULL;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci		/* Validate branch */
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		if (zbr->lnum < c->main_first ||
32062306a36Sopenharmony_ci		    zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
32162306a36Sopenharmony_ci		    zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
32262306a36Sopenharmony_ci			ubifs_err(c, "bad branch %d", i);
32362306a36Sopenharmony_ci			err = 2;
32462306a36Sopenharmony_ci			goto out_dump;
32562306a36Sopenharmony_ci		}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci		switch (key_type(c, &zbr->key)) {
32862306a36Sopenharmony_ci		case UBIFS_INO_KEY:
32962306a36Sopenharmony_ci		case UBIFS_DATA_KEY:
33062306a36Sopenharmony_ci		case UBIFS_DENT_KEY:
33162306a36Sopenharmony_ci		case UBIFS_XENT_KEY:
33262306a36Sopenharmony_ci			break;
33362306a36Sopenharmony_ci		default:
33462306a36Sopenharmony_ci			ubifs_err(c, "bad key type at slot %d: %d",
33562306a36Sopenharmony_ci				  i, key_type(c, &zbr->key));
33662306a36Sopenharmony_ci			err = 3;
33762306a36Sopenharmony_ci			goto out_dump;
33862306a36Sopenharmony_ci		}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci		if (znode->level)
34162306a36Sopenharmony_ci			continue;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		type = key_type(c, &zbr->key);
34462306a36Sopenharmony_ci		if (c->ranges[type].max_len == 0) {
34562306a36Sopenharmony_ci			if (zbr->len != c->ranges[type].len) {
34662306a36Sopenharmony_ci				ubifs_err(c, "bad target node (type %d) length (%d)",
34762306a36Sopenharmony_ci					  type, zbr->len);
34862306a36Sopenharmony_ci				ubifs_err(c, "have to be %d", c->ranges[type].len);
34962306a36Sopenharmony_ci				err = 4;
35062306a36Sopenharmony_ci				goto out_dump;
35162306a36Sopenharmony_ci			}
35262306a36Sopenharmony_ci		} else if (zbr->len < c->ranges[type].min_len ||
35362306a36Sopenharmony_ci			   zbr->len > c->ranges[type].max_len) {
35462306a36Sopenharmony_ci			ubifs_err(c, "bad target node (type %d) length (%d)",
35562306a36Sopenharmony_ci				  type, zbr->len);
35662306a36Sopenharmony_ci			ubifs_err(c, "have to be in range of %d-%d",
35762306a36Sopenharmony_ci				  c->ranges[type].min_len,
35862306a36Sopenharmony_ci				  c->ranges[type].max_len);
35962306a36Sopenharmony_ci			err = 5;
36062306a36Sopenharmony_ci			goto out_dump;
36162306a36Sopenharmony_ci		}
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	/*
36562306a36Sopenharmony_ci	 * Ensure that the next key is greater or equivalent to the
36662306a36Sopenharmony_ci	 * previous one.
36762306a36Sopenharmony_ci	 */
36862306a36Sopenharmony_ci	for (i = 0; i < znode->child_cnt - 1; i++) {
36962306a36Sopenharmony_ci		const union ubifs_key *key1, *key2;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci		key1 = &znode->zbranch[i].key;
37262306a36Sopenharmony_ci		key2 = &znode->zbranch[i + 1].key;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		cmp = keys_cmp(c, key1, key2);
37562306a36Sopenharmony_ci		if (cmp > 0) {
37662306a36Sopenharmony_ci			ubifs_err(c, "bad key order (keys %d and %d)", i, i + 1);
37762306a36Sopenharmony_ci			err = 6;
37862306a36Sopenharmony_ci			goto out_dump;
37962306a36Sopenharmony_ci		} else if (cmp == 0 && !is_hash_key(c, key1)) {
38062306a36Sopenharmony_ci			/* These can only be keys with colliding hash */
38162306a36Sopenharmony_ci			ubifs_err(c, "keys %d and %d are not hashed but equivalent",
38262306a36Sopenharmony_ci				  i, i + 1);
38362306a36Sopenharmony_ci			err = 7;
38462306a36Sopenharmony_ci			goto out_dump;
38562306a36Sopenharmony_ci		}
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	kfree(idx);
38962306a36Sopenharmony_ci	return 0;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ciout_dump:
39262306a36Sopenharmony_ci	ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
39362306a36Sopenharmony_ci	ubifs_dump_node(c, idx, c->max_idx_node_sz);
39462306a36Sopenharmony_ci	kfree(idx);
39562306a36Sopenharmony_ci	return -EINVAL;
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci/**
39962306a36Sopenharmony_ci * ubifs_load_znode - load znode to TNC cache.
40062306a36Sopenharmony_ci * @c: UBIFS file-system description object
40162306a36Sopenharmony_ci * @zbr: znode branch
40262306a36Sopenharmony_ci * @parent: znode's parent
40362306a36Sopenharmony_ci * @iip: index in parent
40462306a36Sopenharmony_ci *
40562306a36Sopenharmony_ci * This function loads znode pointed to by @zbr into the TNC cache and
40662306a36Sopenharmony_ci * returns pointer to it in case of success and a negative error code in case
40762306a36Sopenharmony_ci * of failure.
40862306a36Sopenharmony_ci */
40962306a36Sopenharmony_cistruct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
41062306a36Sopenharmony_ci				     struct ubifs_zbranch *zbr,
41162306a36Sopenharmony_ci				     struct ubifs_znode *parent, int iip)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	int err;
41462306a36Sopenharmony_ci	struct ubifs_znode *znode;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	ubifs_assert(c, !zbr->znode);
41762306a36Sopenharmony_ci	/*
41862306a36Sopenharmony_ci	 * A slab cache is not presently used for znodes because the znode size
41962306a36Sopenharmony_ci	 * depends on the fanout which is stored in the superblock.
42062306a36Sopenharmony_ci	 */
42162306a36Sopenharmony_ci	znode = kzalloc(c->max_znode_sz, GFP_NOFS);
42262306a36Sopenharmony_ci	if (!znode)
42362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	err = read_znode(c, zbr, znode);
42662306a36Sopenharmony_ci	if (err)
42762306a36Sopenharmony_ci		goto out;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	atomic_long_inc(&c->clean_zn_cnt);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/*
43262306a36Sopenharmony_ci	 * Increment the global clean znode counter as well. It is OK that
43362306a36Sopenharmony_ci	 * global and per-FS clean znode counters may be inconsistent for some
43462306a36Sopenharmony_ci	 * short time (because we might be preempted at this point), the global
43562306a36Sopenharmony_ci	 * one is only used in shrinker.
43662306a36Sopenharmony_ci	 */
43762306a36Sopenharmony_ci	atomic_long_inc(&ubifs_clean_zn_cnt);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	zbr->znode = znode;
44062306a36Sopenharmony_ci	znode->parent = parent;
44162306a36Sopenharmony_ci	znode->time = ktime_get_seconds();
44262306a36Sopenharmony_ci	znode->iip = iip;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	return znode;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ciout:
44762306a36Sopenharmony_ci	kfree(znode);
44862306a36Sopenharmony_ci	return ERR_PTR(err);
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci/**
45262306a36Sopenharmony_ci * ubifs_tnc_read_node - read a leaf node from the flash media.
45362306a36Sopenharmony_ci * @c: UBIFS file-system description object
45462306a36Sopenharmony_ci * @zbr: key and position of the node
45562306a36Sopenharmony_ci * @node: node is returned here
45662306a36Sopenharmony_ci *
45762306a36Sopenharmony_ci * This function reads a node defined by @zbr from the flash media. Returns
45862306a36Sopenharmony_ci * zero in case of success or a negative error code in case of failure.
45962306a36Sopenharmony_ci */
46062306a36Sopenharmony_ciint ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
46162306a36Sopenharmony_ci			void *node)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	union ubifs_key key1, *key = &zbr->key;
46462306a36Sopenharmony_ci	int err, type = key_type(c, key);
46562306a36Sopenharmony_ci	struct ubifs_wbuf *wbuf;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	/*
46862306a36Sopenharmony_ci	 * 'zbr' has to point to on-flash node. The node may sit in a bud and
46962306a36Sopenharmony_ci	 * may even be in a write buffer, so we have to take care about this.
47062306a36Sopenharmony_ci	 */
47162306a36Sopenharmony_ci	wbuf = ubifs_get_wbuf(c, zbr->lnum);
47262306a36Sopenharmony_ci	if (wbuf)
47362306a36Sopenharmony_ci		err = ubifs_read_node_wbuf(wbuf, node, type, zbr->len,
47462306a36Sopenharmony_ci					   zbr->lnum, zbr->offs);
47562306a36Sopenharmony_ci	else
47662306a36Sopenharmony_ci		err = ubifs_read_node(c, node, type, zbr->len, zbr->lnum,
47762306a36Sopenharmony_ci				      zbr->offs);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (err) {
48062306a36Sopenharmony_ci		dbg_tnck(key, "key ");
48162306a36Sopenharmony_ci		return err;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	/* Make sure the key of the read node is correct */
48562306a36Sopenharmony_ci	key_read(c, node + UBIFS_KEY_OFFSET, &key1);
48662306a36Sopenharmony_ci	if (!keys_eq(c, key, &key1)) {
48762306a36Sopenharmony_ci		ubifs_err(c, "bad key in node at LEB %d:%d",
48862306a36Sopenharmony_ci			  zbr->lnum, zbr->offs);
48962306a36Sopenharmony_ci		dbg_tnck(key, "looked for key ");
49062306a36Sopenharmony_ci		dbg_tnck(&key1, "but found node's key ");
49162306a36Sopenharmony_ci		ubifs_dump_node(c, node, zbr->len);
49262306a36Sopenharmony_ci		return -EINVAL;
49362306a36Sopenharmony_ci	}
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	err = ubifs_node_check_hash(c, node, zbr->hash);
49662306a36Sopenharmony_ci	if (err) {
49762306a36Sopenharmony_ci		ubifs_bad_hash(c, node, zbr->hash, zbr->lnum, zbr->offs);
49862306a36Sopenharmony_ci		return err;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	return 0;
50262306a36Sopenharmony_ci}
503