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 * Authors: Adrian Hunter
88c2ecf20Sopenharmony_ci *          Artem Bityutskiy (Битюцкий Артём)
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * This file contains journal replay code. It runs when the file-system is being
138c2ecf20Sopenharmony_ci * mounted and requires no locking.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * The larger is the journal, the longer it takes to scan it, so the longer it
168c2ecf20Sopenharmony_ci * takes to mount UBIFS. This is why the journal has limited size which may be
178c2ecf20Sopenharmony_ci * changed depending on the system requirements. But a larger journal gives
188c2ecf20Sopenharmony_ci * faster I/O speed because it writes the index less frequently. So this is a
198c2ecf20Sopenharmony_ci * trade-off. Also, the journal is indexed by the in-memory index (TNC), so the
208c2ecf20Sopenharmony_ci * larger is the journal, the more memory its index may consume.
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "ubifs.h"
248c2ecf20Sopenharmony_ci#include <linux/list_sort.h>
258c2ecf20Sopenharmony_ci#include <crypto/hash.h>
268c2ecf20Sopenharmony_ci#include <crypto/algapi.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/**
298c2ecf20Sopenharmony_ci * struct replay_entry - replay list entry.
308c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number of the node
318c2ecf20Sopenharmony_ci * @offs: node offset
328c2ecf20Sopenharmony_ci * @len: node length
338c2ecf20Sopenharmony_ci * @deletion: non-zero if this entry corresponds to a node deletion
348c2ecf20Sopenharmony_ci * @sqnum: node sequence number
358c2ecf20Sopenharmony_ci * @list: links the replay list
368c2ecf20Sopenharmony_ci * @key: node key
378c2ecf20Sopenharmony_ci * @nm: directory entry name
388c2ecf20Sopenharmony_ci * @old_size: truncation old size
398c2ecf20Sopenharmony_ci * @new_size: truncation new size
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci * The replay process first scans all buds and builds the replay list, then
428c2ecf20Sopenharmony_ci * sorts the replay list in nodes sequence number order, and then inserts all
438c2ecf20Sopenharmony_ci * the replay entries to the TNC.
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_cistruct replay_entry {
468c2ecf20Sopenharmony_ci	int lnum;
478c2ecf20Sopenharmony_ci	int offs;
488c2ecf20Sopenharmony_ci	int len;
498c2ecf20Sopenharmony_ci	u8 hash[UBIFS_HASH_ARR_SZ];
508c2ecf20Sopenharmony_ci	unsigned int deletion:1;
518c2ecf20Sopenharmony_ci	unsigned long long sqnum;
528c2ecf20Sopenharmony_ci	struct list_head list;
538c2ecf20Sopenharmony_ci	union ubifs_key key;
548c2ecf20Sopenharmony_ci	union {
558c2ecf20Sopenharmony_ci		struct fscrypt_name nm;
568c2ecf20Sopenharmony_ci		struct {
578c2ecf20Sopenharmony_ci			loff_t old_size;
588c2ecf20Sopenharmony_ci			loff_t new_size;
598c2ecf20Sopenharmony_ci		};
608c2ecf20Sopenharmony_ci	};
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/**
648c2ecf20Sopenharmony_ci * struct bud_entry - entry in the list of buds to replay.
658c2ecf20Sopenharmony_ci * @list: next bud in the list
668c2ecf20Sopenharmony_ci * @bud: bud description object
678c2ecf20Sopenharmony_ci * @sqnum: reference node sequence number
688c2ecf20Sopenharmony_ci * @free: free bytes in the bud
698c2ecf20Sopenharmony_ci * @dirty: dirty bytes in the bud
708c2ecf20Sopenharmony_ci */
718c2ecf20Sopenharmony_cistruct bud_entry {
728c2ecf20Sopenharmony_ci	struct list_head list;
738c2ecf20Sopenharmony_ci	struct ubifs_bud *bud;
748c2ecf20Sopenharmony_ci	unsigned long long sqnum;
758c2ecf20Sopenharmony_ci	int free;
768c2ecf20Sopenharmony_ci	int dirty;
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/**
808c2ecf20Sopenharmony_ci * set_bud_lprops - set free and dirty space used by a bud.
818c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
828c2ecf20Sopenharmony_ci * @b: bud entry which describes the bud
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * This function makes sure the LEB properties of bud @b are set correctly
858c2ecf20Sopenharmony_ci * after the replay. Returns zero in case of success and a negative error code
868c2ecf20Sopenharmony_ci * in case of failure.
878c2ecf20Sopenharmony_ci */
888c2ecf20Sopenharmony_cistatic int set_bud_lprops(struct ubifs_info *c, struct bud_entry *b)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	const struct ubifs_lprops *lp;
918c2ecf20Sopenharmony_ci	int err = 0, dirty;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	ubifs_get_lprops(c);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	lp = ubifs_lpt_lookup_dirty(c, b->bud->lnum);
968c2ecf20Sopenharmony_ci	if (IS_ERR(lp)) {
978c2ecf20Sopenharmony_ci		err = PTR_ERR(lp);
988c2ecf20Sopenharmony_ci		goto out;
998c2ecf20Sopenharmony_ci	}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	dirty = lp->dirty;
1028c2ecf20Sopenharmony_ci	if (b->bud->start == 0 && (lp->free != c->leb_size || lp->dirty != 0)) {
1038c2ecf20Sopenharmony_ci		/*
1048c2ecf20Sopenharmony_ci		 * The LEB was added to the journal with a starting offset of
1058c2ecf20Sopenharmony_ci		 * zero which means the LEB must have been empty. The LEB
1068c2ecf20Sopenharmony_ci		 * property values should be @lp->free == @c->leb_size and
1078c2ecf20Sopenharmony_ci		 * @lp->dirty == 0, but that is not the case. The reason is that
1088c2ecf20Sopenharmony_ci		 * the LEB had been garbage collected before it became the bud,
1098c2ecf20Sopenharmony_ci		 * and there was not commit inbetween. The garbage collector
1108c2ecf20Sopenharmony_ci		 * resets the free and dirty space without recording it
1118c2ecf20Sopenharmony_ci		 * anywhere except lprops, so if there was no commit then
1128c2ecf20Sopenharmony_ci		 * lprops does not have that information.
1138c2ecf20Sopenharmony_ci		 *
1148c2ecf20Sopenharmony_ci		 * We do not need to adjust free space because the scan has told
1158c2ecf20Sopenharmony_ci		 * us the exact value which is recorded in the replay entry as
1168c2ecf20Sopenharmony_ci		 * @b->free.
1178c2ecf20Sopenharmony_ci		 *
1188c2ecf20Sopenharmony_ci		 * However we do need to subtract from the dirty space the
1198c2ecf20Sopenharmony_ci		 * amount of space that the garbage collector reclaimed, which
1208c2ecf20Sopenharmony_ci		 * is the whole LEB minus the amount of space that was free.
1218c2ecf20Sopenharmony_ci		 */
1228c2ecf20Sopenharmony_ci		dbg_mnt("bud LEB %d was GC'd (%d free, %d dirty)", b->bud->lnum,
1238c2ecf20Sopenharmony_ci			lp->free, lp->dirty);
1248c2ecf20Sopenharmony_ci		dbg_gc("bud LEB %d was GC'd (%d free, %d dirty)", b->bud->lnum,
1258c2ecf20Sopenharmony_ci			lp->free, lp->dirty);
1268c2ecf20Sopenharmony_ci		dirty -= c->leb_size - lp->free;
1278c2ecf20Sopenharmony_ci		/*
1288c2ecf20Sopenharmony_ci		 * If the replay order was perfect the dirty space would now be
1298c2ecf20Sopenharmony_ci		 * zero. The order is not perfect because the journal heads
1308c2ecf20Sopenharmony_ci		 * race with each other. This is not a problem but is does mean
1318c2ecf20Sopenharmony_ci		 * that the dirty space may temporarily exceed c->leb_size
1328c2ecf20Sopenharmony_ci		 * during the replay.
1338c2ecf20Sopenharmony_ci		 */
1348c2ecf20Sopenharmony_ci		if (dirty != 0)
1358c2ecf20Sopenharmony_ci			dbg_mnt("LEB %d lp: %d free %d dirty replay: %d free %d dirty",
1368c2ecf20Sopenharmony_ci				b->bud->lnum, lp->free, lp->dirty, b->free,
1378c2ecf20Sopenharmony_ci				b->dirty);
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci	lp = ubifs_change_lp(c, lp, b->free, dirty + b->dirty,
1408c2ecf20Sopenharmony_ci			     lp->flags | LPROPS_TAKEN, 0);
1418c2ecf20Sopenharmony_ci	if (IS_ERR(lp)) {
1428c2ecf20Sopenharmony_ci		err = PTR_ERR(lp);
1438c2ecf20Sopenharmony_ci		goto out;
1448c2ecf20Sopenharmony_ci	}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	/* Make sure the journal head points to the latest bud */
1478c2ecf20Sopenharmony_ci	err = ubifs_wbuf_seek_nolock(&c->jheads[b->bud->jhead].wbuf,
1488c2ecf20Sopenharmony_ci				     b->bud->lnum, c->leb_size - b->free);
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ciout:
1518c2ecf20Sopenharmony_ci	ubifs_release_lprops(c);
1528c2ecf20Sopenharmony_ci	return err;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/**
1568c2ecf20Sopenharmony_ci * set_buds_lprops - set free and dirty space for all replayed buds.
1578c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
1588c2ecf20Sopenharmony_ci *
1598c2ecf20Sopenharmony_ci * This function sets LEB properties for all replayed buds. Returns zero in
1608c2ecf20Sopenharmony_ci * case of success and a negative error code in case of failure.
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_cistatic int set_buds_lprops(struct ubifs_info *c)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	struct bud_entry *b;
1658c2ecf20Sopenharmony_ci	int err;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	list_for_each_entry(b, &c->replay_buds, list) {
1688c2ecf20Sopenharmony_ci		err = set_bud_lprops(c, b);
1698c2ecf20Sopenharmony_ci		if (err)
1708c2ecf20Sopenharmony_ci			return err;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return 0;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/**
1778c2ecf20Sopenharmony_ci * trun_remove_range - apply a replay entry for a truncation to the TNC.
1788c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
1798c2ecf20Sopenharmony_ci * @r: replay entry of truncation
1808c2ecf20Sopenharmony_ci */
1818c2ecf20Sopenharmony_cistatic int trun_remove_range(struct ubifs_info *c, struct replay_entry *r)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	unsigned min_blk, max_blk;
1848c2ecf20Sopenharmony_ci	union ubifs_key min_key, max_key;
1858c2ecf20Sopenharmony_ci	ino_t ino;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	min_blk = r->new_size / UBIFS_BLOCK_SIZE;
1888c2ecf20Sopenharmony_ci	if (r->new_size & (UBIFS_BLOCK_SIZE - 1))
1898c2ecf20Sopenharmony_ci		min_blk += 1;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	max_blk = r->old_size / UBIFS_BLOCK_SIZE;
1928c2ecf20Sopenharmony_ci	if ((r->old_size & (UBIFS_BLOCK_SIZE - 1)) == 0)
1938c2ecf20Sopenharmony_ci		max_blk -= 1;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	ino = key_inum(c, &r->key);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	data_key_init(c, &min_key, ino, min_blk);
1988c2ecf20Sopenharmony_ci	data_key_init(c, &max_key, ino, max_blk);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	return ubifs_tnc_remove_range(c, &min_key, &max_key);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci/**
2048c2ecf20Sopenharmony_ci * inode_still_linked - check whether inode in question will be re-linked.
2058c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2068c2ecf20Sopenharmony_ci * @rino: replay entry to test
2078c2ecf20Sopenharmony_ci *
2088c2ecf20Sopenharmony_ci * O_TMPFILE files can be re-linked, this means link count goes from 0 to 1.
2098c2ecf20Sopenharmony_ci * This case needs special care, otherwise all references to the inode will
2108c2ecf20Sopenharmony_ci * be removed upon the first replay entry of an inode with link count 0
2118c2ecf20Sopenharmony_ci * is found.
2128c2ecf20Sopenharmony_ci */
2138c2ecf20Sopenharmony_cistatic bool inode_still_linked(struct ubifs_info *c, struct replay_entry *rino)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	struct replay_entry *r;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	ubifs_assert(c, rino->deletion);
2188c2ecf20Sopenharmony_ci	ubifs_assert(c, key_type(c, &rino->key) == UBIFS_INO_KEY);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	/*
2218c2ecf20Sopenharmony_ci	 * Find the most recent entry for the inode behind @rino and check
2228c2ecf20Sopenharmony_ci	 * whether it is a deletion.
2238c2ecf20Sopenharmony_ci	 */
2248c2ecf20Sopenharmony_ci	list_for_each_entry_reverse(r, &c->replay_list, list) {
2258c2ecf20Sopenharmony_ci		ubifs_assert(c, r->sqnum >= rino->sqnum);
2268c2ecf20Sopenharmony_ci		if (key_inum(c, &r->key) == key_inum(c, &rino->key) &&
2278c2ecf20Sopenharmony_ci		    key_type(c, &r->key) == UBIFS_INO_KEY)
2288c2ecf20Sopenharmony_ci			return r->deletion == 0;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	ubifs_assert(c, 0);
2338c2ecf20Sopenharmony_ci	return false;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci/**
2378c2ecf20Sopenharmony_ci * apply_replay_entry - apply a replay entry to the TNC.
2388c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2398c2ecf20Sopenharmony_ci * @r: replay entry to apply
2408c2ecf20Sopenharmony_ci *
2418c2ecf20Sopenharmony_ci * Apply a replay entry to the TNC.
2428c2ecf20Sopenharmony_ci */
2438c2ecf20Sopenharmony_cistatic int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	int err;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	dbg_mntk(&r->key, "LEB %d:%d len %d deletion %d sqnum %llu key ",
2488c2ecf20Sopenharmony_ci		 r->lnum, r->offs, r->len, r->deletion, r->sqnum);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (is_hash_key(c, &r->key)) {
2518c2ecf20Sopenharmony_ci		if (r->deletion)
2528c2ecf20Sopenharmony_ci			err = ubifs_tnc_remove_nm(c, &r->key, &r->nm);
2538c2ecf20Sopenharmony_ci		else
2548c2ecf20Sopenharmony_ci			err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs,
2558c2ecf20Sopenharmony_ci					       r->len, r->hash, &r->nm);
2568c2ecf20Sopenharmony_ci	} else {
2578c2ecf20Sopenharmony_ci		if (r->deletion)
2588c2ecf20Sopenharmony_ci			switch (key_type(c, &r->key)) {
2598c2ecf20Sopenharmony_ci			case UBIFS_INO_KEY:
2608c2ecf20Sopenharmony_ci			{
2618c2ecf20Sopenharmony_ci				ino_t inum = key_inum(c, &r->key);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci				if (inode_still_linked(c, r)) {
2648c2ecf20Sopenharmony_ci					err = 0;
2658c2ecf20Sopenharmony_ci					break;
2668c2ecf20Sopenharmony_ci				}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci				err = ubifs_tnc_remove_ino(c, inum);
2698c2ecf20Sopenharmony_ci				break;
2708c2ecf20Sopenharmony_ci			}
2718c2ecf20Sopenharmony_ci			case UBIFS_TRUN_KEY:
2728c2ecf20Sopenharmony_ci				err = trun_remove_range(c, r);
2738c2ecf20Sopenharmony_ci				break;
2748c2ecf20Sopenharmony_ci			default:
2758c2ecf20Sopenharmony_ci				err = ubifs_tnc_remove(c, &r->key);
2768c2ecf20Sopenharmony_ci				break;
2778c2ecf20Sopenharmony_ci			}
2788c2ecf20Sopenharmony_ci		else
2798c2ecf20Sopenharmony_ci			err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs,
2808c2ecf20Sopenharmony_ci					    r->len, r->hash);
2818c2ecf20Sopenharmony_ci		if (err)
2828c2ecf20Sopenharmony_ci			return err;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		if (c->need_recovery)
2858c2ecf20Sopenharmony_ci			err = ubifs_recover_size_accum(c, &r->key, r->deletion,
2868c2ecf20Sopenharmony_ci						       r->new_size);
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	return err;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci/**
2938c2ecf20Sopenharmony_ci * replay_entries_cmp - compare 2 replay entries.
2948c2ecf20Sopenharmony_ci * @priv: UBIFS file-system description object
2958c2ecf20Sopenharmony_ci * @a: first replay entry
2968c2ecf20Sopenharmony_ci * @b: second replay entry
2978c2ecf20Sopenharmony_ci *
2988c2ecf20Sopenharmony_ci * This is a comparios function for 'list_sort()' which compares 2 replay
2998c2ecf20Sopenharmony_ci * entries @a and @b by comparing their sequence numer.  Returns %1 if @a has
3008c2ecf20Sopenharmony_ci * greater sequence number and %-1 otherwise.
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_cistatic int replay_entries_cmp(void *priv, const struct list_head *a,
3038c2ecf20Sopenharmony_ci			      const struct list_head *b)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	struct ubifs_info *c = priv;
3068c2ecf20Sopenharmony_ci	struct replay_entry *ra, *rb;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	cond_resched();
3098c2ecf20Sopenharmony_ci	if (a == b)
3108c2ecf20Sopenharmony_ci		return 0;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	ra = list_entry(a, struct replay_entry, list);
3138c2ecf20Sopenharmony_ci	rb = list_entry(b, struct replay_entry, list);
3148c2ecf20Sopenharmony_ci	ubifs_assert(c, ra->sqnum != rb->sqnum);
3158c2ecf20Sopenharmony_ci	if (ra->sqnum > rb->sqnum)
3168c2ecf20Sopenharmony_ci		return 1;
3178c2ecf20Sopenharmony_ci	return -1;
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci/**
3218c2ecf20Sopenharmony_ci * apply_replay_list - apply the replay list to the TNC.
3228c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3238c2ecf20Sopenharmony_ci *
3248c2ecf20Sopenharmony_ci * Apply all entries in the replay list to the TNC. Returns zero in case of
3258c2ecf20Sopenharmony_ci * success and a negative error code in case of failure.
3268c2ecf20Sopenharmony_ci */
3278c2ecf20Sopenharmony_cistatic int apply_replay_list(struct ubifs_info *c)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct replay_entry *r;
3308c2ecf20Sopenharmony_ci	int err;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	list_sort(c, &c->replay_list, &replay_entries_cmp);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	list_for_each_entry(r, &c->replay_list, list) {
3358c2ecf20Sopenharmony_ci		cond_resched();
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		err = apply_replay_entry(c, r);
3388c2ecf20Sopenharmony_ci		if (err)
3398c2ecf20Sopenharmony_ci			return err;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci/**
3468c2ecf20Sopenharmony_ci * destroy_replay_list - destroy the replay.
3478c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3488c2ecf20Sopenharmony_ci *
3498c2ecf20Sopenharmony_ci * Destroy the replay list.
3508c2ecf20Sopenharmony_ci */
3518c2ecf20Sopenharmony_cistatic void destroy_replay_list(struct ubifs_info *c)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	struct replay_entry *r, *tmp;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	list_for_each_entry_safe(r, tmp, &c->replay_list, list) {
3568c2ecf20Sopenharmony_ci		if (is_hash_key(c, &r->key))
3578c2ecf20Sopenharmony_ci			kfree(fname_name(&r->nm));
3588c2ecf20Sopenharmony_ci		list_del(&r->list);
3598c2ecf20Sopenharmony_ci		kfree(r);
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci/**
3648c2ecf20Sopenharmony_ci * insert_node - insert a node to the replay list
3658c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3668c2ecf20Sopenharmony_ci * @lnum: node logical eraseblock number
3678c2ecf20Sopenharmony_ci * @offs: node offset
3688c2ecf20Sopenharmony_ci * @len: node length
3698c2ecf20Sopenharmony_ci * @key: node key
3708c2ecf20Sopenharmony_ci * @sqnum: sequence number
3718c2ecf20Sopenharmony_ci * @deletion: non-zero if this is a deletion
3728c2ecf20Sopenharmony_ci * @used: number of bytes in use in a LEB
3738c2ecf20Sopenharmony_ci * @old_size: truncation old size
3748c2ecf20Sopenharmony_ci * @new_size: truncation new size
3758c2ecf20Sopenharmony_ci *
3768c2ecf20Sopenharmony_ci * This function inserts a scanned non-direntry node to the replay list. The
3778c2ecf20Sopenharmony_ci * replay list contains @struct replay_entry elements, and we sort this list in
3788c2ecf20Sopenharmony_ci * sequence number order before applying it. The replay list is applied at the
3798c2ecf20Sopenharmony_ci * very end of the replay process. Since the list is sorted in sequence number
3808c2ecf20Sopenharmony_ci * order, the older modifications are applied first. This function returns zero
3818c2ecf20Sopenharmony_ci * in case of success and a negative error code in case of failure.
3828c2ecf20Sopenharmony_ci */
3838c2ecf20Sopenharmony_cistatic int insert_node(struct ubifs_info *c, int lnum, int offs, int len,
3848c2ecf20Sopenharmony_ci		       const u8 *hash, union ubifs_key *key,
3858c2ecf20Sopenharmony_ci		       unsigned long long sqnum, int deletion, int *used,
3868c2ecf20Sopenharmony_ci		       loff_t old_size, loff_t new_size)
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	struct replay_entry *r;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	if (key_inum(c, key) >= c->highest_inum)
3938c2ecf20Sopenharmony_ci		c->highest_inum = key_inum(c, key);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
3968c2ecf20Sopenharmony_ci	if (!r)
3978c2ecf20Sopenharmony_ci		return -ENOMEM;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	if (!deletion)
4008c2ecf20Sopenharmony_ci		*used += ALIGN(len, 8);
4018c2ecf20Sopenharmony_ci	r->lnum = lnum;
4028c2ecf20Sopenharmony_ci	r->offs = offs;
4038c2ecf20Sopenharmony_ci	r->len = len;
4048c2ecf20Sopenharmony_ci	ubifs_copy_hash(c, hash, r->hash);
4058c2ecf20Sopenharmony_ci	r->deletion = !!deletion;
4068c2ecf20Sopenharmony_ci	r->sqnum = sqnum;
4078c2ecf20Sopenharmony_ci	key_copy(c, key, &r->key);
4088c2ecf20Sopenharmony_ci	r->old_size = old_size;
4098c2ecf20Sopenharmony_ci	r->new_size = new_size;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	list_add_tail(&r->list, &c->replay_list);
4128c2ecf20Sopenharmony_ci	return 0;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci/**
4168c2ecf20Sopenharmony_ci * insert_dent - insert a directory entry node into the replay list.
4178c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4188c2ecf20Sopenharmony_ci * @lnum: node logical eraseblock number
4198c2ecf20Sopenharmony_ci * @offs: node offset
4208c2ecf20Sopenharmony_ci * @len: node length
4218c2ecf20Sopenharmony_ci * @key: node key
4228c2ecf20Sopenharmony_ci * @name: directory entry name
4238c2ecf20Sopenharmony_ci * @nlen: directory entry name length
4248c2ecf20Sopenharmony_ci * @sqnum: sequence number
4258c2ecf20Sopenharmony_ci * @deletion: non-zero if this is a deletion
4268c2ecf20Sopenharmony_ci * @used: number of bytes in use in a LEB
4278c2ecf20Sopenharmony_ci *
4288c2ecf20Sopenharmony_ci * This function inserts a scanned directory entry node or an extended
4298c2ecf20Sopenharmony_ci * attribute entry to the replay list. Returns zero in case of success and a
4308c2ecf20Sopenharmony_ci * negative error code in case of failure.
4318c2ecf20Sopenharmony_ci */
4328c2ecf20Sopenharmony_cistatic int insert_dent(struct ubifs_info *c, int lnum, int offs, int len,
4338c2ecf20Sopenharmony_ci		       const u8 *hash, union ubifs_key *key,
4348c2ecf20Sopenharmony_ci		       const char *name, int nlen, unsigned long long sqnum,
4358c2ecf20Sopenharmony_ci		       int deletion, int *used)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	struct replay_entry *r;
4388c2ecf20Sopenharmony_ci	char *nbuf;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
4418c2ecf20Sopenharmony_ci	if (key_inum(c, key) >= c->highest_inum)
4428c2ecf20Sopenharmony_ci		c->highest_inum = key_inum(c, key);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
4458c2ecf20Sopenharmony_ci	if (!r)
4468c2ecf20Sopenharmony_ci		return -ENOMEM;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	nbuf = kmalloc(nlen + 1, GFP_KERNEL);
4498c2ecf20Sopenharmony_ci	if (!nbuf) {
4508c2ecf20Sopenharmony_ci		kfree(r);
4518c2ecf20Sopenharmony_ci		return -ENOMEM;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	if (!deletion)
4558c2ecf20Sopenharmony_ci		*used += ALIGN(len, 8);
4568c2ecf20Sopenharmony_ci	r->lnum = lnum;
4578c2ecf20Sopenharmony_ci	r->offs = offs;
4588c2ecf20Sopenharmony_ci	r->len = len;
4598c2ecf20Sopenharmony_ci	ubifs_copy_hash(c, hash, r->hash);
4608c2ecf20Sopenharmony_ci	r->deletion = !!deletion;
4618c2ecf20Sopenharmony_ci	r->sqnum = sqnum;
4628c2ecf20Sopenharmony_ci	key_copy(c, key, &r->key);
4638c2ecf20Sopenharmony_ci	fname_len(&r->nm) = nlen;
4648c2ecf20Sopenharmony_ci	memcpy(nbuf, name, nlen);
4658c2ecf20Sopenharmony_ci	nbuf[nlen] = '\0';
4668c2ecf20Sopenharmony_ci	fname_name(&r->nm) = nbuf;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	list_add_tail(&r->list, &c->replay_list);
4698c2ecf20Sopenharmony_ci	return 0;
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci/**
4738c2ecf20Sopenharmony_ci * ubifs_validate_entry - validate directory or extended attribute entry node.
4748c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4758c2ecf20Sopenharmony_ci * @dent: the node to validate
4768c2ecf20Sopenharmony_ci *
4778c2ecf20Sopenharmony_ci * This function validates directory or extended attribute entry node @dent.
4788c2ecf20Sopenharmony_ci * Returns zero if the node is all right and a %-EINVAL if not.
4798c2ecf20Sopenharmony_ci */
4808c2ecf20Sopenharmony_ciint ubifs_validate_entry(struct ubifs_info *c,
4818c2ecf20Sopenharmony_ci			 const struct ubifs_dent_node *dent)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	int key_type = key_type_flash(c, dent->key);
4848c2ecf20Sopenharmony_ci	int nlen = le16_to_cpu(dent->nlen);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	if (le32_to_cpu(dent->ch.len) != nlen + UBIFS_DENT_NODE_SZ + 1 ||
4878c2ecf20Sopenharmony_ci	    dent->type >= UBIFS_ITYPES_CNT ||
4888c2ecf20Sopenharmony_ci	    nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 ||
4898c2ecf20Sopenharmony_ci	    (key_type == UBIFS_XENT_KEY && strnlen(dent->name, nlen) != nlen) ||
4908c2ecf20Sopenharmony_ci	    le64_to_cpu(dent->inum) > MAX_INUM) {
4918c2ecf20Sopenharmony_ci		ubifs_err(c, "bad %s node", key_type == UBIFS_DENT_KEY ?
4928c2ecf20Sopenharmony_ci			  "directory entry" : "extended attribute entry");
4938c2ecf20Sopenharmony_ci		return -EINVAL;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) {
4978c2ecf20Sopenharmony_ci		ubifs_err(c, "bad key type %d", key_type);
4988c2ecf20Sopenharmony_ci		return -EINVAL;
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	return 0;
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci/**
5058c2ecf20Sopenharmony_ci * is_last_bud - check if the bud is the last in the journal head.
5068c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
5078c2ecf20Sopenharmony_ci * @bud: bud description object
5088c2ecf20Sopenharmony_ci *
5098c2ecf20Sopenharmony_ci * This function checks if bud @bud is the last bud in its journal head. This
5108c2ecf20Sopenharmony_ci * information is then used by 'replay_bud()' to decide whether the bud can
5118c2ecf20Sopenharmony_ci * have corruptions or not. Indeed, only last buds can be corrupted by power
5128c2ecf20Sopenharmony_ci * cuts. Returns %1 if this is the last bud, and %0 if not.
5138c2ecf20Sopenharmony_ci */
5148c2ecf20Sopenharmony_cistatic int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct ubifs_jhead *jh = &c->jheads[bud->jhead];
5178c2ecf20Sopenharmony_ci	struct ubifs_bud *next;
5188c2ecf20Sopenharmony_ci	uint32_t data;
5198c2ecf20Sopenharmony_ci	int err;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	if (list_is_last(&bud->list, &jh->buds_list))
5228c2ecf20Sopenharmony_ci		return 1;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	/*
5258c2ecf20Sopenharmony_ci	 * The following is a quirk to make sure we work correctly with UBIFS
5268c2ecf20Sopenharmony_ci	 * images used with older UBIFS.
5278c2ecf20Sopenharmony_ci	 *
5288c2ecf20Sopenharmony_ci	 * Normally, the last bud will be the last in the journal head's list
5298c2ecf20Sopenharmony_ci	 * of bud. However, there is one exception if the UBIFS image belongs
5308c2ecf20Sopenharmony_ci	 * to older UBIFS. This is fairly unlikely: one would need to use old
5318c2ecf20Sopenharmony_ci	 * UBIFS, then have a power cut exactly at the right point, and then
5328c2ecf20Sopenharmony_ci	 * try to mount this image with new UBIFS.
5338c2ecf20Sopenharmony_ci	 *
5348c2ecf20Sopenharmony_ci	 * The exception is: it is possible to have 2 buds A and B, A goes
5358c2ecf20Sopenharmony_ci	 * before B, and B is the last, bud B is contains no data, and bud A is
5368c2ecf20Sopenharmony_ci	 * corrupted at the end. The reason is that in older versions when the
5378c2ecf20Sopenharmony_ci	 * journal code switched the next bud (from A to B), it first added a
5388c2ecf20Sopenharmony_ci	 * log reference node for the new bud (B), and only after this it
5398c2ecf20Sopenharmony_ci	 * synchronized the write-buffer of current bud (A). But later this was
5408c2ecf20Sopenharmony_ci	 * changed and UBIFS started to always synchronize the write-buffer of
5418c2ecf20Sopenharmony_ci	 * the bud (A) before writing the log reference for the new bud (B).
5428c2ecf20Sopenharmony_ci	 *
5438c2ecf20Sopenharmony_ci	 * But because older UBIFS always synchronized A's write-buffer before
5448c2ecf20Sopenharmony_ci	 * writing to B, we can recognize this exceptional situation but
5458c2ecf20Sopenharmony_ci	 * checking the contents of bud B - if it is empty, then A can be
5468c2ecf20Sopenharmony_ci	 * treated as the last and we can recover it.
5478c2ecf20Sopenharmony_ci	 *
5488c2ecf20Sopenharmony_ci	 * TODO: remove this piece of code in a couple of years (today it is
5498c2ecf20Sopenharmony_ci	 * 16.05.2011).
5508c2ecf20Sopenharmony_ci	 */
5518c2ecf20Sopenharmony_ci	next = list_entry(bud->list.next, struct ubifs_bud, list);
5528c2ecf20Sopenharmony_ci	if (!list_is_last(&next->list, &jh->buds_list))
5538c2ecf20Sopenharmony_ci		return 0;
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
5568c2ecf20Sopenharmony_ci	if (err)
5578c2ecf20Sopenharmony_ci		return 0;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	return data == 0xFFFFFFFF;
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci/* authenticate_sleb_hash is split out for stack usage */
5638c2ecf20Sopenharmony_cistatic int noinline_for_stack
5648c2ecf20Sopenharmony_ciauthenticate_sleb_hash(struct ubifs_info *c,
5658c2ecf20Sopenharmony_ci		       struct shash_desc *log_hash, u8 *hash)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	SHASH_DESC_ON_STACK(hash_desc, c->hash_tfm);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	hash_desc->tfm = c->hash_tfm;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	ubifs_shash_copy_state(c, log_hash, hash_desc);
5728c2ecf20Sopenharmony_ci	return crypto_shash_final(hash_desc, hash);
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci/**
5768c2ecf20Sopenharmony_ci * authenticate_sleb - authenticate one scan LEB
5778c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
5788c2ecf20Sopenharmony_ci * @sleb: the scan LEB to authenticate
5798c2ecf20Sopenharmony_ci * @log_hash:
5808c2ecf20Sopenharmony_ci * @is_last: if true, this is is the last LEB
5818c2ecf20Sopenharmony_ci *
5828c2ecf20Sopenharmony_ci * This function iterates over the buds of a single LEB authenticating all buds
5838c2ecf20Sopenharmony_ci * with the authentication nodes on this LEB. Authentication nodes are written
5848c2ecf20Sopenharmony_ci * after some buds and contain a HMAC covering the authentication node itself
5858c2ecf20Sopenharmony_ci * and the buds between the last authentication node and the current
5868c2ecf20Sopenharmony_ci * authentication node. It can happen that the last buds cannot be authenticated
5878c2ecf20Sopenharmony_ci * because a powercut happened when some nodes were written but not the
5888c2ecf20Sopenharmony_ci * corresponding authentication node. This function returns the number of nodes
5898c2ecf20Sopenharmony_ci * that could be authenticated or a negative error code.
5908c2ecf20Sopenharmony_ci */
5918c2ecf20Sopenharmony_cistatic int authenticate_sleb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
5928c2ecf20Sopenharmony_ci			     struct shash_desc *log_hash, int is_last)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	int n_not_auth = 0;
5958c2ecf20Sopenharmony_ci	struct ubifs_scan_node *snod;
5968c2ecf20Sopenharmony_ci	int n_nodes = 0;
5978c2ecf20Sopenharmony_ci	int err;
5988c2ecf20Sopenharmony_ci	u8 hash[UBIFS_HASH_ARR_SZ];
5998c2ecf20Sopenharmony_ci	u8 hmac[UBIFS_HMAC_ARR_SZ];
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	if (!ubifs_authenticated(c))
6028c2ecf20Sopenharmony_ci		return sleb->nodes_cnt;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	list_for_each_entry(snod, &sleb->nodes, list) {
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci		n_nodes++;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci		if (snod->type == UBIFS_AUTH_NODE) {
6098c2ecf20Sopenharmony_ci			struct ubifs_auth_node *auth = snod->node;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci			err = authenticate_sleb_hash(c, log_hash, hash);
6128c2ecf20Sopenharmony_ci			if (err)
6138c2ecf20Sopenharmony_ci				goto out;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci			err = crypto_shash_tfm_digest(c->hmac_tfm, hash,
6168c2ecf20Sopenharmony_ci						      c->hash_len, hmac);
6178c2ecf20Sopenharmony_ci			if (err)
6188c2ecf20Sopenharmony_ci				goto out;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci			err = ubifs_check_hmac(c, auth->hmac, hmac);
6218c2ecf20Sopenharmony_ci			if (err) {
6228c2ecf20Sopenharmony_ci				err = -EPERM;
6238c2ecf20Sopenharmony_ci				goto out;
6248c2ecf20Sopenharmony_ci			}
6258c2ecf20Sopenharmony_ci			n_not_auth = 0;
6268c2ecf20Sopenharmony_ci		} else {
6278c2ecf20Sopenharmony_ci			err = crypto_shash_update(log_hash, snod->node,
6288c2ecf20Sopenharmony_ci						  snod->len);
6298c2ecf20Sopenharmony_ci			if (err)
6308c2ecf20Sopenharmony_ci				goto out;
6318c2ecf20Sopenharmony_ci			n_not_auth++;
6328c2ecf20Sopenharmony_ci		}
6338c2ecf20Sopenharmony_ci	}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	/*
6368c2ecf20Sopenharmony_ci	 * A powercut can happen when some nodes were written, but not yet
6378c2ecf20Sopenharmony_ci	 * the corresponding authentication node. This may only happen on
6388c2ecf20Sopenharmony_ci	 * the last bud though.
6398c2ecf20Sopenharmony_ci	 */
6408c2ecf20Sopenharmony_ci	if (n_not_auth) {
6418c2ecf20Sopenharmony_ci		if (is_last) {
6428c2ecf20Sopenharmony_ci			dbg_mnt("%d unauthenticated nodes found on LEB %d, Ignoring them",
6438c2ecf20Sopenharmony_ci				n_not_auth, sleb->lnum);
6448c2ecf20Sopenharmony_ci			err = 0;
6458c2ecf20Sopenharmony_ci		} else {
6468c2ecf20Sopenharmony_ci			dbg_mnt("%d unauthenticated nodes found on non-last LEB %d",
6478c2ecf20Sopenharmony_ci				n_not_auth, sleb->lnum);
6488c2ecf20Sopenharmony_ci			err = -EPERM;
6498c2ecf20Sopenharmony_ci		}
6508c2ecf20Sopenharmony_ci	} else {
6518c2ecf20Sopenharmony_ci		err = 0;
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ciout:
6548c2ecf20Sopenharmony_ci	return err ? err : n_nodes - n_not_auth;
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci/**
6588c2ecf20Sopenharmony_ci * replay_bud - replay a bud logical eraseblock.
6598c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
6608c2ecf20Sopenharmony_ci * @b: bud entry which describes the bud
6618c2ecf20Sopenharmony_ci *
6628c2ecf20Sopenharmony_ci * This function replays bud @bud, recovers it if needed, and adds all nodes
6638c2ecf20Sopenharmony_ci * from this bud to the replay list. Returns zero in case of success and a
6648c2ecf20Sopenharmony_ci * negative error code in case of failure.
6658c2ecf20Sopenharmony_ci */
6668c2ecf20Sopenharmony_cistatic int replay_bud(struct ubifs_info *c, struct bud_entry *b)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	int is_last = is_last_bud(c, b->bud);
6698c2ecf20Sopenharmony_ci	int err = 0, used = 0, lnum = b->bud->lnum, offs = b->bud->start;
6708c2ecf20Sopenharmony_ci	int n_nodes, n = 0;
6718c2ecf20Sopenharmony_ci	struct ubifs_scan_leb *sleb;
6728c2ecf20Sopenharmony_ci	struct ubifs_scan_node *snod;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	dbg_mnt("replay bud LEB %d, head %d, offs %d, is_last %d",
6758c2ecf20Sopenharmony_ci		lnum, b->bud->jhead, offs, is_last);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (c->need_recovery && is_last)
6788c2ecf20Sopenharmony_ci		/*
6798c2ecf20Sopenharmony_ci		 * Recover only last LEBs in the journal heads, because power
6808c2ecf20Sopenharmony_ci		 * cuts may cause corruptions only in these LEBs, because only
6818c2ecf20Sopenharmony_ci		 * these LEBs could possibly be written to at the power cut
6828c2ecf20Sopenharmony_ci		 * time.
6838c2ecf20Sopenharmony_ci		 */
6848c2ecf20Sopenharmony_ci		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);
6858c2ecf20Sopenharmony_ci	else
6868c2ecf20Sopenharmony_ci		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
6878c2ecf20Sopenharmony_ci	if (IS_ERR(sleb))
6888c2ecf20Sopenharmony_ci		return PTR_ERR(sleb);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	n_nodes = authenticate_sleb(c, sleb, b->bud->log_hash, is_last);
6918c2ecf20Sopenharmony_ci	if (n_nodes < 0) {
6928c2ecf20Sopenharmony_ci		err = n_nodes;
6938c2ecf20Sopenharmony_ci		goto out;
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	ubifs_shash_copy_state(c, b->bud->log_hash,
6978c2ecf20Sopenharmony_ci			       c->jheads[b->bud->jhead].log_hash);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	/*
7008c2ecf20Sopenharmony_ci	 * The bud does not have to start from offset zero - the beginning of
7018c2ecf20Sopenharmony_ci	 * the 'lnum' LEB may contain previously committed data. One of the
7028c2ecf20Sopenharmony_ci	 * things we have to do in replay is to correctly update lprops with
7038c2ecf20Sopenharmony_ci	 * newer information about this LEB.
7048c2ecf20Sopenharmony_ci	 *
7058c2ecf20Sopenharmony_ci	 * At this point lprops thinks that this LEB has 'c->leb_size - offs'
7068c2ecf20Sopenharmony_ci	 * bytes of free space because it only contain information about
7078c2ecf20Sopenharmony_ci	 * committed data.
7088c2ecf20Sopenharmony_ci	 *
7098c2ecf20Sopenharmony_ci	 * But we know that real amount of free space is 'c->leb_size -
7108c2ecf20Sopenharmony_ci	 * sleb->endpt', and the space in the 'lnum' LEB between 'offs' and
7118c2ecf20Sopenharmony_ci	 * 'sleb->endpt' is used by bud data. We have to correctly calculate
7128c2ecf20Sopenharmony_ci	 * how much of these data are dirty and update lprops with this
7138c2ecf20Sopenharmony_ci	 * information.
7148c2ecf20Sopenharmony_ci	 *
7158c2ecf20Sopenharmony_ci	 * The dirt in that LEB region is comprised of padding nodes, deletion
7168c2ecf20Sopenharmony_ci	 * nodes, truncation nodes and nodes which are obsoleted by subsequent
7178c2ecf20Sopenharmony_ci	 * nodes in this LEB. So instead of calculating clean space, we
7188c2ecf20Sopenharmony_ci	 * calculate used space ('used' variable).
7198c2ecf20Sopenharmony_ci	 */
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	list_for_each_entry(snod, &sleb->nodes, list) {
7228c2ecf20Sopenharmony_ci		u8 hash[UBIFS_HASH_ARR_SZ];
7238c2ecf20Sopenharmony_ci		int deletion = 0;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci		cond_resched();
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci		if (snod->sqnum >= SQNUM_WATERMARK) {
7288c2ecf20Sopenharmony_ci			ubifs_err(c, "file system's life ended");
7298c2ecf20Sopenharmony_ci			goto out_dump;
7308c2ecf20Sopenharmony_ci		}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci		ubifs_node_calc_hash(c, snod->node, hash);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		if (snod->sqnum > c->max_sqnum)
7358c2ecf20Sopenharmony_ci			c->max_sqnum = snod->sqnum;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci		switch (snod->type) {
7388c2ecf20Sopenharmony_ci		case UBIFS_INO_NODE:
7398c2ecf20Sopenharmony_ci		{
7408c2ecf20Sopenharmony_ci			struct ubifs_ino_node *ino = snod->node;
7418c2ecf20Sopenharmony_ci			loff_t new_size = le64_to_cpu(ino->size);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci			if (le32_to_cpu(ino->nlink) == 0)
7448c2ecf20Sopenharmony_ci				deletion = 1;
7458c2ecf20Sopenharmony_ci			err = insert_node(c, lnum, snod->offs, snod->len, hash,
7468c2ecf20Sopenharmony_ci					  &snod->key, snod->sqnum, deletion,
7478c2ecf20Sopenharmony_ci					  &used, 0, new_size);
7488c2ecf20Sopenharmony_ci			break;
7498c2ecf20Sopenharmony_ci		}
7508c2ecf20Sopenharmony_ci		case UBIFS_DATA_NODE:
7518c2ecf20Sopenharmony_ci		{
7528c2ecf20Sopenharmony_ci			struct ubifs_data_node *dn = snod->node;
7538c2ecf20Sopenharmony_ci			loff_t new_size = le32_to_cpu(dn->size) +
7548c2ecf20Sopenharmony_ci					  key_block(c, &snod->key) *
7558c2ecf20Sopenharmony_ci					  UBIFS_BLOCK_SIZE;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci			err = insert_node(c, lnum, snod->offs, snod->len, hash,
7588c2ecf20Sopenharmony_ci					  &snod->key, snod->sqnum, deletion,
7598c2ecf20Sopenharmony_ci					  &used, 0, new_size);
7608c2ecf20Sopenharmony_ci			break;
7618c2ecf20Sopenharmony_ci		}
7628c2ecf20Sopenharmony_ci		case UBIFS_DENT_NODE:
7638c2ecf20Sopenharmony_ci		case UBIFS_XENT_NODE:
7648c2ecf20Sopenharmony_ci		{
7658c2ecf20Sopenharmony_ci			struct ubifs_dent_node *dent = snod->node;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci			err = ubifs_validate_entry(c, dent);
7688c2ecf20Sopenharmony_ci			if (err)
7698c2ecf20Sopenharmony_ci				goto out_dump;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci			err = insert_dent(c, lnum, snod->offs, snod->len, hash,
7728c2ecf20Sopenharmony_ci					  &snod->key, dent->name,
7738c2ecf20Sopenharmony_ci					  le16_to_cpu(dent->nlen), snod->sqnum,
7748c2ecf20Sopenharmony_ci					  !le64_to_cpu(dent->inum), &used);
7758c2ecf20Sopenharmony_ci			break;
7768c2ecf20Sopenharmony_ci		}
7778c2ecf20Sopenharmony_ci		case UBIFS_TRUN_NODE:
7788c2ecf20Sopenharmony_ci		{
7798c2ecf20Sopenharmony_ci			struct ubifs_trun_node *trun = snod->node;
7808c2ecf20Sopenharmony_ci			loff_t old_size = le64_to_cpu(trun->old_size);
7818c2ecf20Sopenharmony_ci			loff_t new_size = le64_to_cpu(trun->new_size);
7828c2ecf20Sopenharmony_ci			union ubifs_key key;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci			/* Validate truncation node */
7858c2ecf20Sopenharmony_ci			if (old_size < 0 || old_size > c->max_inode_sz ||
7868c2ecf20Sopenharmony_ci			    new_size < 0 || new_size > c->max_inode_sz ||
7878c2ecf20Sopenharmony_ci			    old_size <= new_size) {
7888c2ecf20Sopenharmony_ci				ubifs_err(c, "bad truncation node");
7898c2ecf20Sopenharmony_ci				goto out_dump;
7908c2ecf20Sopenharmony_ci			}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci			/*
7938c2ecf20Sopenharmony_ci			 * Create a fake truncation key just to use the same
7948c2ecf20Sopenharmony_ci			 * functions which expect nodes to have keys.
7958c2ecf20Sopenharmony_ci			 */
7968c2ecf20Sopenharmony_ci			trun_key_init(c, &key, le32_to_cpu(trun->inum));
7978c2ecf20Sopenharmony_ci			err = insert_node(c, lnum, snod->offs, snod->len, hash,
7988c2ecf20Sopenharmony_ci					  &key, snod->sqnum, 1, &used,
7998c2ecf20Sopenharmony_ci					  old_size, new_size);
8008c2ecf20Sopenharmony_ci			break;
8018c2ecf20Sopenharmony_ci		}
8028c2ecf20Sopenharmony_ci		case UBIFS_AUTH_NODE:
8038c2ecf20Sopenharmony_ci			break;
8048c2ecf20Sopenharmony_ci		default:
8058c2ecf20Sopenharmony_ci			ubifs_err(c, "unexpected node type %d in bud LEB %d:%d",
8068c2ecf20Sopenharmony_ci				  snod->type, lnum, snod->offs);
8078c2ecf20Sopenharmony_ci			err = -EINVAL;
8088c2ecf20Sopenharmony_ci			goto out_dump;
8098c2ecf20Sopenharmony_ci		}
8108c2ecf20Sopenharmony_ci		if (err)
8118c2ecf20Sopenharmony_ci			goto out;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		n++;
8148c2ecf20Sopenharmony_ci		if (n == n_nodes)
8158c2ecf20Sopenharmony_ci			break;
8168c2ecf20Sopenharmony_ci	}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	ubifs_assert(c, ubifs_search_bud(c, lnum));
8198c2ecf20Sopenharmony_ci	ubifs_assert(c, sleb->endpt - offs >= used);
8208c2ecf20Sopenharmony_ci	ubifs_assert(c, sleb->endpt % c->min_io_size == 0);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	b->dirty = sleb->endpt - offs - used;
8238c2ecf20Sopenharmony_ci	b->free = c->leb_size - sleb->endpt;
8248c2ecf20Sopenharmony_ci	dbg_mnt("bud LEB %d replied: dirty %d, free %d",
8258c2ecf20Sopenharmony_ci		lnum, b->dirty, b->free);
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ciout:
8288c2ecf20Sopenharmony_ci	ubifs_scan_destroy(sleb);
8298c2ecf20Sopenharmony_ci	return err;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ciout_dump:
8328c2ecf20Sopenharmony_ci	ubifs_err(c, "bad node is at LEB %d:%d", lnum, snod->offs);
8338c2ecf20Sopenharmony_ci	ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
8348c2ecf20Sopenharmony_ci	ubifs_scan_destroy(sleb);
8358c2ecf20Sopenharmony_ci	return -EINVAL;
8368c2ecf20Sopenharmony_ci}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci/**
8398c2ecf20Sopenharmony_ci * replay_buds - replay all buds.
8408c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
8418c2ecf20Sopenharmony_ci *
8428c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
8438c2ecf20Sopenharmony_ci * case of failure.
8448c2ecf20Sopenharmony_ci */
8458c2ecf20Sopenharmony_cistatic int replay_buds(struct ubifs_info *c)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	struct bud_entry *b;
8488c2ecf20Sopenharmony_ci	int err;
8498c2ecf20Sopenharmony_ci	unsigned long long prev_sqnum = 0;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	list_for_each_entry(b, &c->replay_buds, list) {
8528c2ecf20Sopenharmony_ci		err = replay_bud(c, b);
8538c2ecf20Sopenharmony_ci		if (err)
8548c2ecf20Sopenharmony_ci			return err;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci		ubifs_assert(c, b->sqnum > prev_sqnum);
8578c2ecf20Sopenharmony_ci		prev_sqnum = b->sqnum;
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	return 0;
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci/**
8648c2ecf20Sopenharmony_ci * destroy_bud_list - destroy the list of buds to replay.
8658c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
8668c2ecf20Sopenharmony_ci */
8678c2ecf20Sopenharmony_cistatic void destroy_bud_list(struct ubifs_info *c)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	struct bud_entry *b;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	while (!list_empty(&c->replay_buds)) {
8728c2ecf20Sopenharmony_ci		b = list_entry(c->replay_buds.next, struct bud_entry, list);
8738c2ecf20Sopenharmony_ci		list_del(&b->list);
8748c2ecf20Sopenharmony_ci		kfree(b);
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci/**
8798c2ecf20Sopenharmony_ci * add_replay_bud - add a bud to the list of buds to replay.
8808c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
8818c2ecf20Sopenharmony_ci * @lnum: bud logical eraseblock number to replay
8828c2ecf20Sopenharmony_ci * @offs: bud start offset
8838c2ecf20Sopenharmony_ci * @jhead: journal head to which this bud belongs
8848c2ecf20Sopenharmony_ci * @sqnum: reference node sequence number
8858c2ecf20Sopenharmony_ci *
8868c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
8878c2ecf20Sopenharmony_ci * case of failure.
8888c2ecf20Sopenharmony_ci */
8898c2ecf20Sopenharmony_cistatic int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
8908c2ecf20Sopenharmony_ci			  unsigned long long sqnum)
8918c2ecf20Sopenharmony_ci{
8928c2ecf20Sopenharmony_ci	struct ubifs_bud *bud;
8938c2ecf20Sopenharmony_ci	struct bud_entry *b;
8948c2ecf20Sopenharmony_ci	int err;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	bud = kmalloc(sizeof(struct ubifs_bud), GFP_KERNEL);
8998c2ecf20Sopenharmony_ci	if (!bud)
9008c2ecf20Sopenharmony_ci		return -ENOMEM;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL);
9038c2ecf20Sopenharmony_ci	if (!b) {
9048c2ecf20Sopenharmony_ci		err = -ENOMEM;
9058c2ecf20Sopenharmony_ci		goto out;
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	bud->lnum = lnum;
9098c2ecf20Sopenharmony_ci	bud->start = offs;
9108c2ecf20Sopenharmony_ci	bud->jhead = jhead;
9118c2ecf20Sopenharmony_ci	bud->log_hash = ubifs_hash_get_desc(c);
9128c2ecf20Sopenharmony_ci	if (IS_ERR(bud->log_hash)) {
9138c2ecf20Sopenharmony_ci		err = PTR_ERR(bud->log_hash);
9148c2ecf20Sopenharmony_ci		goto out;
9158c2ecf20Sopenharmony_ci	}
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	ubifs_shash_copy_state(c, c->log_hash, bud->log_hash);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	ubifs_add_bud(c, bud);
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	b->bud = bud;
9228c2ecf20Sopenharmony_ci	b->sqnum = sqnum;
9238c2ecf20Sopenharmony_ci	list_add_tail(&b->list, &c->replay_buds);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return 0;
9268c2ecf20Sopenharmony_ciout:
9278c2ecf20Sopenharmony_ci	kfree(bud);
9288c2ecf20Sopenharmony_ci	kfree(b);
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	return err;
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci/**
9348c2ecf20Sopenharmony_ci * validate_ref - validate a reference node.
9358c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9368c2ecf20Sopenharmony_ci * @ref: the reference node to validate
9378c2ecf20Sopenharmony_ci *
9388c2ecf20Sopenharmony_ci * This function returns %1 if a bud reference already exists for the LEB. %0 is
9398c2ecf20Sopenharmony_ci * returned if the reference node is new, otherwise %-EINVAL is returned if
9408c2ecf20Sopenharmony_ci * validation failed.
9418c2ecf20Sopenharmony_ci */
9428c2ecf20Sopenharmony_cistatic int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref)
9438c2ecf20Sopenharmony_ci{
9448c2ecf20Sopenharmony_ci	struct ubifs_bud *bud;
9458c2ecf20Sopenharmony_ci	int lnum = le32_to_cpu(ref->lnum);
9468c2ecf20Sopenharmony_ci	unsigned int offs = le32_to_cpu(ref->offs);
9478c2ecf20Sopenharmony_ci	unsigned int jhead = le32_to_cpu(ref->jhead);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	/*
9508c2ecf20Sopenharmony_ci	 * ref->offs may point to the end of LEB when the journal head points
9518c2ecf20Sopenharmony_ci	 * to the end of LEB and we write reference node for it during commit.
9528c2ecf20Sopenharmony_ci	 * So this is why we require 'offs > c->leb_size'.
9538c2ecf20Sopenharmony_ci	 */
9548c2ecf20Sopenharmony_ci	if (jhead >= c->jhead_cnt || lnum >= c->leb_cnt ||
9558c2ecf20Sopenharmony_ci	    lnum < c->main_first || offs > c->leb_size ||
9568c2ecf20Sopenharmony_ci	    offs & (c->min_io_size - 1))
9578c2ecf20Sopenharmony_ci		return -EINVAL;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	/* Make sure we have not already looked at this bud */
9608c2ecf20Sopenharmony_ci	bud = ubifs_search_bud(c, lnum);
9618c2ecf20Sopenharmony_ci	if (bud) {
9628c2ecf20Sopenharmony_ci		if (bud->jhead == jhead && bud->start <= offs)
9638c2ecf20Sopenharmony_ci			return 1;
9648c2ecf20Sopenharmony_ci		ubifs_err(c, "bud at LEB %d:%d was already referred", lnum, offs);
9658c2ecf20Sopenharmony_ci		return -EINVAL;
9668c2ecf20Sopenharmony_ci	}
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	return 0;
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci/**
9728c2ecf20Sopenharmony_ci * replay_log_leb - replay a log logical eraseblock.
9738c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9748c2ecf20Sopenharmony_ci * @lnum: log logical eraseblock to replay
9758c2ecf20Sopenharmony_ci * @offs: offset to start replaying from
9768c2ecf20Sopenharmony_ci * @sbuf: scan buffer
9778c2ecf20Sopenharmony_ci *
9788c2ecf20Sopenharmony_ci * This function replays a log LEB and returns zero in case of success, %1 if
9798c2ecf20Sopenharmony_ci * this is the last LEB in the log, and a negative error code in case of
9808c2ecf20Sopenharmony_ci * failure.
9818c2ecf20Sopenharmony_ci */
9828c2ecf20Sopenharmony_cistatic int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
9838c2ecf20Sopenharmony_ci{
9848c2ecf20Sopenharmony_ci	int err;
9858c2ecf20Sopenharmony_ci	struct ubifs_scan_leb *sleb;
9868c2ecf20Sopenharmony_ci	struct ubifs_scan_node *snod;
9878c2ecf20Sopenharmony_ci	const struct ubifs_cs_node *node;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	dbg_mnt("replay log LEB %d:%d", lnum, offs);
9908c2ecf20Sopenharmony_ci	sleb = ubifs_scan(c, lnum, offs, sbuf, c->need_recovery);
9918c2ecf20Sopenharmony_ci	if (IS_ERR(sleb)) {
9928c2ecf20Sopenharmony_ci		if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
9938c2ecf20Sopenharmony_ci			return PTR_ERR(sleb);
9948c2ecf20Sopenharmony_ci		/*
9958c2ecf20Sopenharmony_ci		 * Note, the below function will recover this log LEB only if
9968c2ecf20Sopenharmony_ci		 * it is the last, because unclean reboots can possibly corrupt
9978c2ecf20Sopenharmony_ci		 * only the tail of the log.
9988c2ecf20Sopenharmony_ci		 */
9998c2ecf20Sopenharmony_ci		sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
10008c2ecf20Sopenharmony_ci		if (IS_ERR(sleb))
10018c2ecf20Sopenharmony_ci			return PTR_ERR(sleb);
10028c2ecf20Sopenharmony_ci	}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	if (sleb->nodes_cnt == 0) {
10058c2ecf20Sopenharmony_ci		err = 1;
10068c2ecf20Sopenharmony_ci		goto out;
10078c2ecf20Sopenharmony_ci	}
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	node = sleb->buf;
10108c2ecf20Sopenharmony_ci	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
10118c2ecf20Sopenharmony_ci	if (c->cs_sqnum == 0) {
10128c2ecf20Sopenharmony_ci		/*
10138c2ecf20Sopenharmony_ci		 * This is the first log LEB we are looking at, make sure that
10148c2ecf20Sopenharmony_ci		 * the first node is a commit start node. Also record its
10158c2ecf20Sopenharmony_ci		 * sequence number so that UBIFS can determine where the log
10168c2ecf20Sopenharmony_ci		 * ends, because all nodes which were have higher sequence
10178c2ecf20Sopenharmony_ci		 * numbers.
10188c2ecf20Sopenharmony_ci		 */
10198c2ecf20Sopenharmony_ci		if (snod->type != UBIFS_CS_NODE) {
10208c2ecf20Sopenharmony_ci			ubifs_err(c, "first log node at LEB %d:%d is not CS node",
10218c2ecf20Sopenharmony_ci				  lnum, offs);
10228c2ecf20Sopenharmony_ci			goto out_dump;
10238c2ecf20Sopenharmony_ci		}
10248c2ecf20Sopenharmony_ci		if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
10258c2ecf20Sopenharmony_ci			ubifs_err(c, "first CS node at LEB %d:%d has wrong commit number %llu expected %llu",
10268c2ecf20Sopenharmony_ci				  lnum, offs,
10278c2ecf20Sopenharmony_ci				  (unsigned long long)le64_to_cpu(node->cmt_no),
10288c2ecf20Sopenharmony_ci				  c->cmt_no);
10298c2ecf20Sopenharmony_ci			goto out_dump;
10308c2ecf20Sopenharmony_ci		}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci		c->cs_sqnum = le64_to_cpu(node->ch.sqnum);
10338c2ecf20Sopenharmony_ci		dbg_mnt("commit start sqnum %llu", c->cs_sqnum);
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci		err = ubifs_shash_init(c, c->log_hash);
10368c2ecf20Sopenharmony_ci		if (err)
10378c2ecf20Sopenharmony_ci			goto out;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci		err = ubifs_shash_update(c, c->log_hash, node, UBIFS_CS_NODE_SZ);
10408c2ecf20Sopenharmony_ci		if (err < 0)
10418c2ecf20Sopenharmony_ci			goto out;
10428c2ecf20Sopenharmony_ci	}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (snod->sqnum < c->cs_sqnum) {
10458c2ecf20Sopenharmony_ci		/*
10468c2ecf20Sopenharmony_ci		 * This means that we reached end of log and now
10478c2ecf20Sopenharmony_ci		 * look to the older log data, which was already
10488c2ecf20Sopenharmony_ci		 * committed but the eraseblock was not erased (UBIFS
10498c2ecf20Sopenharmony_ci		 * only un-maps it). So this basically means we have to
10508c2ecf20Sopenharmony_ci		 * exit with "end of log" code.
10518c2ecf20Sopenharmony_ci		 */
10528c2ecf20Sopenharmony_ci		err = 1;
10538c2ecf20Sopenharmony_ci		goto out;
10548c2ecf20Sopenharmony_ci	}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	/* Make sure the first node sits at offset zero of the LEB */
10578c2ecf20Sopenharmony_ci	if (snod->offs != 0) {
10588c2ecf20Sopenharmony_ci		ubifs_err(c, "first node is not at zero offset");
10598c2ecf20Sopenharmony_ci		goto out_dump;
10608c2ecf20Sopenharmony_ci	}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	list_for_each_entry(snod, &sleb->nodes, list) {
10638c2ecf20Sopenharmony_ci		cond_resched();
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci		if (snod->sqnum >= SQNUM_WATERMARK) {
10668c2ecf20Sopenharmony_ci			ubifs_err(c, "file system's life ended");
10678c2ecf20Sopenharmony_ci			goto out_dump;
10688c2ecf20Sopenharmony_ci		}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci		if (snod->sqnum < c->cs_sqnum) {
10718c2ecf20Sopenharmony_ci			ubifs_err(c, "bad sqnum %llu, commit sqnum %llu",
10728c2ecf20Sopenharmony_ci				  snod->sqnum, c->cs_sqnum);
10738c2ecf20Sopenharmony_ci			goto out_dump;
10748c2ecf20Sopenharmony_ci		}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		if (snod->sqnum > c->max_sqnum)
10778c2ecf20Sopenharmony_ci			c->max_sqnum = snod->sqnum;
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci		switch (snod->type) {
10808c2ecf20Sopenharmony_ci		case UBIFS_REF_NODE: {
10818c2ecf20Sopenharmony_ci			const struct ubifs_ref_node *ref = snod->node;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci			err = validate_ref(c, ref);
10848c2ecf20Sopenharmony_ci			if (err == 1)
10858c2ecf20Sopenharmony_ci				break; /* Already have this bud */
10868c2ecf20Sopenharmony_ci			if (err)
10878c2ecf20Sopenharmony_ci				goto out_dump;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci			err = ubifs_shash_update(c, c->log_hash, ref,
10908c2ecf20Sopenharmony_ci						 UBIFS_REF_NODE_SZ);
10918c2ecf20Sopenharmony_ci			if (err)
10928c2ecf20Sopenharmony_ci				goto out;
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci			err = add_replay_bud(c, le32_to_cpu(ref->lnum),
10958c2ecf20Sopenharmony_ci					     le32_to_cpu(ref->offs),
10968c2ecf20Sopenharmony_ci					     le32_to_cpu(ref->jhead),
10978c2ecf20Sopenharmony_ci					     snod->sqnum);
10988c2ecf20Sopenharmony_ci			if (err)
10998c2ecf20Sopenharmony_ci				goto out;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci			break;
11028c2ecf20Sopenharmony_ci		}
11038c2ecf20Sopenharmony_ci		case UBIFS_CS_NODE:
11048c2ecf20Sopenharmony_ci			/* Make sure it sits at the beginning of LEB */
11058c2ecf20Sopenharmony_ci			if (snod->offs != 0) {
11068c2ecf20Sopenharmony_ci				ubifs_err(c, "unexpected node in log");
11078c2ecf20Sopenharmony_ci				goto out_dump;
11088c2ecf20Sopenharmony_ci			}
11098c2ecf20Sopenharmony_ci			break;
11108c2ecf20Sopenharmony_ci		default:
11118c2ecf20Sopenharmony_ci			ubifs_err(c, "unexpected node in log");
11128c2ecf20Sopenharmony_ci			goto out_dump;
11138c2ecf20Sopenharmony_ci		}
11148c2ecf20Sopenharmony_ci	}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	if (sleb->endpt || c->lhead_offs >= c->leb_size) {
11178c2ecf20Sopenharmony_ci		c->lhead_lnum = lnum;
11188c2ecf20Sopenharmony_ci		c->lhead_offs = sleb->endpt;
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	err = !sleb->endpt;
11228c2ecf20Sopenharmony_ciout:
11238c2ecf20Sopenharmony_ci	ubifs_scan_destroy(sleb);
11248c2ecf20Sopenharmony_ci	return err;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ciout_dump:
11278c2ecf20Sopenharmony_ci	ubifs_err(c, "log error detected while replaying the log at LEB %d:%d",
11288c2ecf20Sopenharmony_ci		  lnum, offs + snod->offs);
11298c2ecf20Sopenharmony_ci	ubifs_dump_node(c, snod->node, c->leb_size - snod->offs);
11308c2ecf20Sopenharmony_ci	ubifs_scan_destroy(sleb);
11318c2ecf20Sopenharmony_ci	return -EINVAL;
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci/**
11358c2ecf20Sopenharmony_ci * take_ihead - update the status of the index head in lprops to 'taken'.
11368c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
11378c2ecf20Sopenharmony_ci *
11388c2ecf20Sopenharmony_ci * This function returns the amount of free space in the index head LEB or a
11398c2ecf20Sopenharmony_ci * negative error code.
11408c2ecf20Sopenharmony_ci */
11418c2ecf20Sopenharmony_cistatic int take_ihead(struct ubifs_info *c)
11428c2ecf20Sopenharmony_ci{
11438c2ecf20Sopenharmony_ci	const struct ubifs_lprops *lp;
11448c2ecf20Sopenharmony_ci	int err, free;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	ubifs_get_lprops(c);
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	lp = ubifs_lpt_lookup_dirty(c, c->ihead_lnum);
11498c2ecf20Sopenharmony_ci	if (IS_ERR(lp)) {
11508c2ecf20Sopenharmony_ci		err = PTR_ERR(lp);
11518c2ecf20Sopenharmony_ci		goto out;
11528c2ecf20Sopenharmony_ci	}
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	free = lp->free;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
11578c2ecf20Sopenharmony_ci			     lp->flags | LPROPS_TAKEN, 0);
11588c2ecf20Sopenharmony_ci	if (IS_ERR(lp)) {
11598c2ecf20Sopenharmony_ci		err = PTR_ERR(lp);
11608c2ecf20Sopenharmony_ci		goto out;
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	err = free;
11648c2ecf20Sopenharmony_ciout:
11658c2ecf20Sopenharmony_ci	ubifs_release_lprops(c);
11668c2ecf20Sopenharmony_ci	return err;
11678c2ecf20Sopenharmony_ci}
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci/**
11708c2ecf20Sopenharmony_ci * ubifs_replay_journal - replay journal.
11718c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
11728c2ecf20Sopenharmony_ci *
11738c2ecf20Sopenharmony_ci * This function scans the journal, replays and cleans it up. It makes sure all
11748c2ecf20Sopenharmony_ci * memory data structures related to uncommitted journal are built (dirty TNC
11758c2ecf20Sopenharmony_ci * tree, tree of buds, modified lprops, etc).
11768c2ecf20Sopenharmony_ci */
11778c2ecf20Sopenharmony_ciint ubifs_replay_journal(struct ubifs_info *c)
11788c2ecf20Sopenharmony_ci{
11798c2ecf20Sopenharmony_ci	int err, lnum, free;
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	/* Update the status of the index head in lprops to 'taken' */
11848c2ecf20Sopenharmony_ci	free = take_ihead(c);
11858c2ecf20Sopenharmony_ci	if (free < 0)
11868c2ecf20Sopenharmony_ci		return free; /* Error code */
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	if (c->ihead_offs != c->leb_size - free) {
11898c2ecf20Sopenharmony_ci		ubifs_err(c, "bad index head LEB %d:%d", c->ihead_lnum,
11908c2ecf20Sopenharmony_ci			  c->ihead_offs);
11918c2ecf20Sopenharmony_ci		return -EINVAL;
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	dbg_mnt("start replaying the journal");
11958c2ecf20Sopenharmony_ci	c->replaying = 1;
11968c2ecf20Sopenharmony_ci	lnum = c->ltail_lnum = c->lhead_lnum;
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	do {
11998c2ecf20Sopenharmony_ci		err = replay_log_leb(c, lnum, 0, c->sbuf);
12008c2ecf20Sopenharmony_ci		if (err == 1) {
12018c2ecf20Sopenharmony_ci			if (lnum != c->lhead_lnum)
12028c2ecf20Sopenharmony_ci				/* We hit the end of the log */
12038c2ecf20Sopenharmony_ci				break;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci			/*
12068c2ecf20Sopenharmony_ci			 * The head of the log must always start with the
12078c2ecf20Sopenharmony_ci			 * "commit start" node on a properly formatted UBIFS.
12088c2ecf20Sopenharmony_ci			 * But we found no nodes at all, which means that
12098c2ecf20Sopenharmony_ci			 * something went wrong and we cannot proceed mounting
12108c2ecf20Sopenharmony_ci			 * the file-system.
12118c2ecf20Sopenharmony_ci			 */
12128c2ecf20Sopenharmony_ci			ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
12138c2ecf20Sopenharmony_ci				  lnum, 0);
12148c2ecf20Sopenharmony_ci			err = -EINVAL;
12158c2ecf20Sopenharmony_ci		}
12168c2ecf20Sopenharmony_ci		if (err)
12178c2ecf20Sopenharmony_ci			goto out;
12188c2ecf20Sopenharmony_ci		lnum = ubifs_next_log_lnum(c, lnum);
12198c2ecf20Sopenharmony_ci	} while (lnum != c->ltail_lnum);
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	err = replay_buds(c);
12228c2ecf20Sopenharmony_ci	if (err)
12238c2ecf20Sopenharmony_ci		goto out;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	err = apply_replay_list(c);
12268c2ecf20Sopenharmony_ci	if (err)
12278c2ecf20Sopenharmony_ci		goto out;
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	err = set_buds_lprops(c);
12308c2ecf20Sopenharmony_ci	if (err)
12318c2ecf20Sopenharmony_ci		goto out;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	/*
12348c2ecf20Sopenharmony_ci	 * UBIFS budgeting calculations use @c->bi.uncommitted_idx variable
12358c2ecf20Sopenharmony_ci	 * to roughly estimate index growth. Things like @c->bi.min_idx_lebs
12368c2ecf20Sopenharmony_ci	 * depend on it. This means we have to initialize it to make sure
12378c2ecf20Sopenharmony_ci	 * budgeting works properly.
12388c2ecf20Sopenharmony_ci	 */
12398c2ecf20Sopenharmony_ci	c->bi.uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt);
12408c2ecf20Sopenharmony_ci	c->bi.uncommitted_idx *= c->max_idx_node_sz;
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	ubifs_assert(c, c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
12438c2ecf20Sopenharmony_ci	dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, highest_inum %lu",
12448c2ecf20Sopenharmony_ci		c->lhead_lnum, c->lhead_offs, c->max_sqnum,
12458c2ecf20Sopenharmony_ci		(unsigned long)c->highest_inum);
12468c2ecf20Sopenharmony_ciout:
12478c2ecf20Sopenharmony_ci	destroy_replay_list(c);
12488c2ecf20Sopenharmony_ci	destroy_bud_list(c);
12498c2ecf20Sopenharmony_ci	c->replaying = 0;
12508c2ecf20Sopenharmony_ci	return err;
12518c2ecf20Sopenharmony_ci}
1252