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 implements functions needed to recover from unclean un-mounts.
138c2ecf20Sopenharmony_ci * When UBIFS is mounted, it checks a flag on the master node to determine if
148c2ecf20Sopenharmony_ci * an un-mount was completed successfully. If not, the process of mounting
158c2ecf20Sopenharmony_ci * incorporates additional checking and fixing of on-flash data structures.
168c2ecf20Sopenharmony_ci * UBIFS always cleans away all remnants of an unclean un-mount, so that
178c2ecf20Sopenharmony_ci * errors do not accumulate. However UBIFS defers recovery if it is mounted
188c2ecf20Sopenharmony_ci * read-only, and the flash is not modified in that case.
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * The general UBIFS approach to the recovery is that it recovers from
218c2ecf20Sopenharmony_ci * corruptions which could be caused by power cuts, but it refuses to recover
228c2ecf20Sopenharmony_ci * from corruption caused by other reasons. And UBIFS tries to distinguish
238c2ecf20Sopenharmony_ci * between these 2 reasons of corruptions and silently recover in the former
248c2ecf20Sopenharmony_ci * case and loudly complain in the latter case.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * UBIFS writes only to erased LEBs, so it writes only to the flash space
278c2ecf20Sopenharmony_ci * containing only 0xFFs. UBIFS also always writes strictly from the beginning
288c2ecf20Sopenharmony_ci * of the LEB to the end. And UBIFS assumes that the underlying flash media
298c2ecf20Sopenharmony_ci * writes in @c->max_write_size bytes at a time.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min.
328c2ecf20Sopenharmony_ci * I/O unit corresponding to offset X to contain corrupted data, all the
338c2ecf20Sopenharmony_ci * following min. I/O units have to contain empty space (all 0xFFs). If this is
348c2ecf20Sopenharmony_ci * not true, the corruption cannot be the result of a power cut, and UBIFS
358c2ecf20Sopenharmony_ci * refuses to mount.
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include <linux/crc32.h>
398c2ecf20Sopenharmony_ci#include <linux/slab.h>
408c2ecf20Sopenharmony_ci#include "ubifs.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/**
438c2ecf20Sopenharmony_ci * is_empty - determine whether a buffer is empty (contains all 0xff).
448c2ecf20Sopenharmony_ci * @buf: buffer to clean
458c2ecf20Sopenharmony_ci * @len: length of buffer
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci * This function returns %1 if the buffer is empty (contains all 0xff) otherwise
488c2ecf20Sopenharmony_ci * %0 is returned.
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_cistatic int is_empty(void *buf, int len)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	uint8_t *p = buf;
538c2ecf20Sopenharmony_ci	int i;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++)
568c2ecf20Sopenharmony_ci		if (*p++ != 0xff)
578c2ecf20Sopenharmony_ci			return 0;
588c2ecf20Sopenharmony_ci	return 1;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/**
628c2ecf20Sopenharmony_ci * first_non_ff - find offset of the first non-0xff byte.
638c2ecf20Sopenharmony_ci * @buf: buffer to search in
648c2ecf20Sopenharmony_ci * @len: length of buffer
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci * This function returns offset of the first non-0xff byte in @buf or %-1 if
678c2ecf20Sopenharmony_ci * the buffer contains only 0xff bytes.
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_cistatic int first_non_ff(void *buf, int len)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	uint8_t *p = buf;
728c2ecf20Sopenharmony_ci	int i;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++)
758c2ecf20Sopenharmony_ci		if (*p++ != 0xff)
768c2ecf20Sopenharmony_ci			return i;
778c2ecf20Sopenharmony_ci	return -1;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/**
818c2ecf20Sopenharmony_ci * get_master_node - get the last valid master node allowing for corruption.
828c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
838c2ecf20Sopenharmony_ci * @lnum: LEB number
848c2ecf20Sopenharmony_ci * @pbuf: buffer containing the LEB read, is returned here
858c2ecf20Sopenharmony_ci * @mst: master node, if found, is returned here
868c2ecf20Sopenharmony_ci * @cor: corruption, if found, is returned here
878c2ecf20Sopenharmony_ci *
888c2ecf20Sopenharmony_ci * This function allocates a buffer, reads the LEB into it, and finds and
898c2ecf20Sopenharmony_ci * returns the last valid master node allowing for one area of corruption.
908c2ecf20Sopenharmony_ci * The corrupt area, if there is one, must be consistent with the assumption
918c2ecf20Sopenharmony_ci * that it is the result of an unclean unmount while the master node was being
928c2ecf20Sopenharmony_ci * written. Under those circumstances, it is valid to use the previously written
938c2ecf20Sopenharmony_ci * master node.
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cistatic int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
988c2ecf20Sopenharmony_ci			   struct ubifs_mst_node **mst, void **cor)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	const int sz = c->mst_node_alsz;
1018c2ecf20Sopenharmony_ci	int err, offs, len;
1028c2ecf20Sopenharmony_ci	void *sbuf, *buf;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	sbuf = vmalloc(c->leb_size);
1058c2ecf20Sopenharmony_ci	if (!sbuf)
1068c2ecf20Sopenharmony_ci		return -ENOMEM;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
1098c2ecf20Sopenharmony_ci	if (err && err != -EBADMSG)
1108c2ecf20Sopenharmony_ci		goto out_free;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	/* Find the first position that is definitely not a node */
1138c2ecf20Sopenharmony_ci	offs = 0;
1148c2ecf20Sopenharmony_ci	buf = sbuf;
1158c2ecf20Sopenharmony_ci	len = c->leb_size;
1168c2ecf20Sopenharmony_ci	while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) {
1178c2ecf20Sopenharmony_ci		struct ubifs_ch *ch = buf;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci		if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC)
1208c2ecf20Sopenharmony_ci			break;
1218c2ecf20Sopenharmony_ci		offs += sz;
1228c2ecf20Sopenharmony_ci		buf  += sz;
1238c2ecf20Sopenharmony_ci		len  -= sz;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci	/* See if there was a valid master node before that */
1268c2ecf20Sopenharmony_ci	if (offs) {
1278c2ecf20Sopenharmony_ci		int ret;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci		offs -= sz;
1308c2ecf20Sopenharmony_ci		buf  -= sz;
1318c2ecf20Sopenharmony_ci		len  += sz;
1328c2ecf20Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
1338c2ecf20Sopenharmony_ci		if (ret != SCANNED_A_NODE && offs) {
1348c2ecf20Sopenharmony_ci			/* Could have been corruption so check one place back */
1358c2ecf20Sopenharmony_ci			offs -= sz;
1368c2ecf20Sopenharmony_ci			buf  -= sz;
1378c2ecf20Sopenharmony_ci			len  += sz;
1388c2ecf20Sopenharmony_ci			ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
1398c2ecf20Sopenharmony_ci			if (ret != SCANNED_A_NODE)
1408c2ecf20Sopenharmony_ci				/*
1418c2ecf20Sopenharmony_ci				 * We accept only one area of corruption because
1428c2ecf20Sopenharmony_ci				 * we are assuming that it was caused while
1438c2ecf20Sopenharmony_ci				 * trying to write a master node.
1448c2ecf20Sopenharmony_ci				 */
1458c2ecf20Sopenharmony_ci				goto out_err;
1468c2ecf20Sopenharmony_ci		}
1478c2ecf20Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
1488c2ecf20Sopenharmony_ci			struct ubifs_ch *ch = buf;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci			if (ch->node_type != UBIFS_MST_NODE)
1518c2ecf20Sopenharmony_ci				goto out_err;
1528c2ecf20Sopenharmony_ci			dbg_rcvry("found a master node at %d:%d", lnum, offs);
1538c2ecf20Sopenharmony_ci			*mst = buf;
1548c2ecf20Sopenharmony_ci			offs += sz;
1558c2ecf20Sopenharmony_ci			buf  += sz;
1568c2ecf20Sopenharmony_ci			len  -= sz;
1578c2ecf20Sopenharmony_ci		}
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci	/* Check for corruption */
1608c2ecf20Sopenharmony_ci	if (offs < c->leb_size) {
1618c2ecf20Sopenharmony_ci		if (!is_empty(buf, min_t(int, len, sz))) {
1628c2ecf20Sopenharmony_ci			*cor = buf;
1638c2ecf20Sopenharmony_ci			dbg_rcvry("found corruption at %d:%d", lnum, offs);
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci		offs += sz;
1668c2ecf20Sopenharmony_ci		buf  += sz;
1678c2ecf20Sopenharmony_ci		len  -= sz;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci	/* Check remaining empty space */
1708c2ecf20Sopenharmony_ci	if (offs < c->leb_size)
1718c2ecf20Sopenharmony_ci		if (!is_empty(buf, len))
1728c2ecf20Sopenharmony_ci			goto out_err;
1738c2ecf20Sopenharmony_ci	*pbuf = sbuf;
1748c2ecf20Sopenharmony_ci	return 0;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciout_err:
1778c2ecf20Sopenharmony_ci	err = -EINVAL;
1788c2ecf20Sopenharmony_ciout_free:
1798c2ecf20Sopenharmony_ci	vfree(sbuf);
1808c2ecf20Sopenharmony_ci	*mst = NULL;
1818c2ecf20Sopenharmony_ci	*cor = NULL;
1828c2ecf20Sopenharmony_ci	return err;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci/**
1868c2ecf20Sopenharmony_ci * write_rcvrd_mst_node - write recovered master node.
1878c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
1888c2ecf20Sopenharmony_ci * @mst: master node
1898c2ecf20Sopenharmony_ci *
1908c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
1918c2ecf20Sopenharmony_ci */
1928c2ecf20Sopenharmony_cistatic int write_rcvrd_mst_node(struct ubifs_info *c,
1938c2ecf20Sopenharmony_ci				struct ubifs_mst_node *mst)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz;
1968c2ecf20Sopenharmony_ci	__le32 save_flags;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	dbg_rcvry("recovery");
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	save_flags = mst->flags;
2018c2ecf20Sopenharmony_ci	mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ,
2048c2ecf20Sopenharmony_ci				      offsetof(struct ubifs_mst_node, hmac), 1);
2058c2ecf20Sopenharmony_ci	if (err)
2068c2ecf20Sopenharmony_ci		goto out;
2078c2ecf20Sopenharmony_ci	err = ubifs_leb_change(c, lnum, mst, sz);
2088c2ecf20Sopenharmony_ci	if (err)
2098c2ecf20Sopenharmony_ci		goto out;
2108c2ecf20Sopenharmony_ci	err = ubifs_leb_change(c, lnum + 1, mst, sz);
2118c2ecf20Sopenharmony_ci	if (err)
2128c2ecf20Sopenharmony_ci		goto out;
2138c2ecf20Sopenharmony_ciout:
2148c2ecf20Sopenharmony_ci	mst->flags = save_flags;
2158c2ecf20Sopenharmony_ci	return err;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci/**
2198c2ecf20Sopenharmony_ci * ubifs_recover_master_node - recover the master node.
2208c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2218c2ecf20Sopenharmony_ci *
2228c2ecf20Sopenharmony_ci * This function recovers the master node from corruption that may occur due to
2238c2ecf20Sopenharmony_ci * an unclean unmount.
2248c2ecf20Sopenharmony_ci *
2258c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
2268c2ecf20Sopenharmony_ci */
2278c2ecf20Sopenharmony_ciint ubifs_recover_master_node(struct ubifs_info *c)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL;
2308c2ecf20Sopenharmony_ci	struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst;
2318c2ecf20Sopenharmony_ci	const int sz = c->mst_node_alsz;
2328c2ecf20Sopenharmony_ci	int err, offs1, offs2;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	dbg_rcvry("recovery");
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1);
2378c2ecf20Sopenharmony_ci	if (err)
2388c2ecf20Sopenharmony_ci		goto out_free;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2);
2418c2ecf20Sopenharmony_ci	if (err)
2428c2ecf20Sopenharmony_ci		goto out_free;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (mst1) {
2458c2ecf20Sopenharmony_ci		offs1 = (void *)mst1 - buf1;
2468c2ecf20Sopenharmony_ci		if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) &&
2478c2ecf20Sopenharmony_ci		    (offs1 == 0 && !cor1)) {
2488c2ecf20Sopenharmony_ci			/*
2498c2ecf20Sopenharmony_ci			 * mst1 was written by recovery at offset 0 with no
2508c2ecf20Sopenharmony_ci			 * corruption.
2518c2ecf20Sopenharmony_ci			 */
2528c2ecf20Sopenharmony_ci			dbg_rcvry("recovery recovery");
2538c2ecf20Sopenharmony_ci			mst = mst1;
2548c2ecf20Sopenharmony_ci		} else if (mst2) {
2558c2ecf20Sopenharmony_ci			offs2 = (void *)mst2 - buf2;
2568c2ecf20Sopenharmony_ci			if (offs1 == offs2) {
2578c2ecf20Sopenharmony_ci				/* Same offset, so must be the same */
2588c2ecf20Sopenharmony_ci				if (ubifs_compare_master_node(c, mst1, mst2))
2598c2ecf20Sopenharmony_ci					goto out_err;
2608c2ecf20Sopenharmony_ci				mst = mst1;
2618c2ecf20Sopenharmony_ci			} else if (offs2 + sz == offs1) {
2628c2ecf20Sopenharmony_ci				/* 1st LEB was written, 2nd was not */
2638c2ecf20Sopenharmony_ci				if (cor1)
2648c2ecf20Sopenharmony_ci					goto out_err;
2658c2ecf20Sopenharmony_ci				mst = mst1;
2668c2ecf20Sopenharmony_ci			} else if (offs1 == 0 &&
2678c2ecf20Sopenharmony_ci				   c->leb_size - offs2 - sz < sz) {
2688c2ecf20Sopenharmony_ci				/* 1st LEB was unmapped and written, 2nd not */
2698c2ecf20Sopenharmony_ci				if (cor1)
2708c2ecf20Sopenharmony_ci					goto out_err;
2718c2ecf20Sopenharmony_ci				mst = mst1;
2728c2ecf20Sopenharmony_ci			} else
2738c2ecf20Sopenharmony_ci				goto out_err;
2748c2ecf20Sopenharmony_ci		} else {
2758c2ecf20Sopenharmony_ci			/*
2768c2ecf20Sopenharmony_ci			 * 2nd LEB was unmapped and about to be written, so
2778c2ecf20Sopenharmony_ci			 * there must be only one master node in the first LEB
2788c2ecf20Sopenharmony_ci			 * and no corruption.
2798c2ecf20Sopenharmony_ci			 */
2808c2ecf20Sopenharmony_ci			if (offs1 != 0 || cor1)
2818c2ecf20Sopenharmony_ci				goto out_err;
2828c2ecf20Sopenharmony_ci			mst = mst1;
2838c2ecf20Sopenharmony_ci		}
2848c2ecf20Sopenharmony_ci	} else {
2858c2ecf20Sopenharmony_ci		if (!mst2)
2868c2ecf20Sopenharmony_ci			goto out_err;
2878c2ecf20Sopenharmony_ci		/*
2888c2ecf20Sopenharmony_ci		 * 1st LEB was unmapped and about to be written, so there must
2898c2ecf20Sopenharmony_ci		 * be no room left in 2nd LEB.
2908c2ecf20Sopenharmony_ci		 */
2918c2ecf20Sopenharmony_ci		offs2 = (void *)mst2 - buf2;
2928c2ecf20Sopenharmony_ci		if (offs2 + sz + sz <= c->leb_size)
2938c2ecf20Sopenharmony_ci			goto out_err;
2948c2ecf20Sopenharmony_ci		mst = mst2;
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	ubifs_msg(c, "recovered master node from LEB %d",
2988c2ecf20Sopenharmony_ci		  (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1));
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (c->ro_mount) {
3038c2ecf20Sopenharmony_ci		/* Read-only mode. Keep a copy for switching to rw mode */
3048c2ecf20Sopenharmony_ci		c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
3058c2ecf20Sopenharmony_ci		if (!c->rcvrd_mst_node) {
3068c2ecf20Sopenharmony_ci			err = -ENOMEM;
3078c2ecf20Sopenharmony_ci			goto out_free;
3088c2ecf20Sopenharmony_ci		}
3098c2ecf20Sopenharmony_ci		memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci		/*
3128c2ecf20Sopenharmony_ci		 * We had to recover the master node, which means there was an
3138c2ecf20Sopenharmony_ci		 * unclean reboot. However, it is possible that the master node
3148c2ecf20Sopenharmony_ci		 * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
3158c2ecf20Sopenharmony_ci		 * E.g., consider the following chain of events:
3168c2ecf20Sopenharmony_ci		 *
3178c2ecf20Sopenharmony_ci		 * 1. UBIFS was cleanly unmounted, so the master node is clean
3188c2ecf20Sopenharmony_ci		 * 2. UBIFS is being mounted R/W and starts changing the master
3198c2ecf20Sopenharmony_ci		 *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
3208c2ecf20Sopenharmony_ci		 *    so this LEB ends up with some amount of garbage at the
3218c2ecf20Sopenharmony_ci		 *    end.
3228c2ecf20Sopenharmony_ci		 * 3. UBIFS is being mounted R/O. We reach this place and
3238c2ecf20Sopenharmony_ci		 *    recover the master node from the second LEB
3248c2ecf20Sopenharmony_ci		 *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
3258c2ecf20Sopenharmony_ci		 *    because we are being mounted R/O. We have to defer the
3268c2ecf20Sopenharmony_ci		 *    operation.
3278c2ecf20Sopenharmony_ci		 * 4. However, this master node (@c->mst_node) is marked as
3288c2ecf20Sopenharmony_ci		 *    clean (since the step 1). And if we just return, the
3298c2ecf20Sopenharmony_ci		 *    mount code will be confused and won't recover the master
3308c2ecf20Sopenharmony_ci		 *    node when it is re-mounter R/W later.
3318c2ecf20Sopenharmony_ci		 *
3328c2ecf20Sopenharmony_ci		 *    Thus, to force the recovery by marking the master node as
3338c2ecf20Sopenharmony_ci		 *    dirty.
3348c2ecf20Sopenharmony_ci		 */
3358c2ecf20Sopenharmony_ci		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
3368c2ecf20Sopenharmony_ci	} else {
3378c2ecf20Sopenharmony_ci		/* Write the recovered master node */
3388c2ecf20Sopenharmony_ci		c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
3398c2ecf20Sopenharmony_ci		err = write_rcvrd_mst_node(c, c->mst_node);
3408c2ecf20Sopenharmony_ci		if (err)
3418c2ecf20Sopenharmony_ci			goto out_free;
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	vfree(buf2);
3458c2ecf20Sopenharmony_ci	vfree(buf1);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return 0;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ciout_err:
3508c2ecf20Sopenharmony_ci	err = -EINVAL;
3518c2ecf20Sopenharmony_ciout_free:
3528c2ecf20Sopenharmony_ci	ubifs_err(c, "failed to recover master node");
3538c2ecf20Sopenharmony_ci	if (mst1) {
3548c2ecf20Sopenharmony_ci		ubifs_err(c, "dumping first master node");
3558c2ecf20Sopenharmony_ci		ubifs_dump_node(c, mst1, c->leb_size - ((void *)mst1 - buf1));
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci	if (mst2) {
3588c2ecf20Sopenharmony_ci		ubifs_err(c, "dumping second master node");
3598c2ecf20Sopenharmony_ci		ubifs_dump_node(c, mst2, c->leb_size - ((void *)mst2 - buf2));
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci	vfree(buf2);
3628c2ecf20Sopenharmony_ci	vfree(buf1);
3638c2ecf20Sopenharmony_ci	return err;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci/**
3678c2ecf20Sopenharmony_ci * ubifs_write_rcvrd_mst_node - write the recovered master node.
3688c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3698c2ecf20Sopenharmony_ci *
3708c2ecf20Sopenharmony_ci * This function writes the master node that was recovered during mounting in
3718c2ecf20Sopenharmony_ci * read-only mode and must now be written because we are remounting rw.
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_ciint ubifs_write_rcvrd_mst_node(struct ubifs_info *c)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	int err;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	if (!c->rcvrd_mst_node)
3808c2ecf20Sopenharmony_ci		return 0;
3818c2ecf20Sopenharmony_ci	c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
3828c2ecf20Sopenharmony_ci	c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
3838c2ecf20Sopenharmony_ci	err = write_rcvrd_mst_node(c, c->rcvrd_mst_node);
3848c2ecf20Sopenharmony_ci	if (err)
3858c2ecf20Sopenharmony_ci		return err;
3868c2ecf20Sopenharmony_ci	kfree(c->rcvrd_mst_node);
3878c2ecf20Sopenharmony_ci	c->rcvrd_mst_node = NULL;
3888c2ecf20Sopenharmony_ci	return 0;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci/**
3928c2ecf20Sopenharmony_ci * is_last_write - determine if an offset was in the last write to a LEB.
3938c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3948c2ecf20Sopenharmony_ci * @buf: buffer to check
3958c2ecf20Sopenharmony_ci * @offs: offset to check
3968c2ecf20Sopenharmony_ci *
3978c2ecf20Sopenharmony_ci * This function returns %1 if @offs was in the last write to the LEB whose data
3988c2ecf20Sopenharmony_ci * is in @buf, otherwise %0 is returned. The determination is made by checking
3998c2ecf20Sopenharmony_ci * for subsequent empty space starting from the next @c->max_write_size
4008c2ecf20Sopenharmony_ci * boundary.
4018c2ecf20Sopenharmony_ci */
4028c2ecf20Sopenharmony_cistatic int is_last_write(const struct ubifs_info *c, void *buf, int offs)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	int empty_offs, check_len;
4058c2ecf20Sopenharmony_ci	uint8_t *p;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	/*
4088c2ecf20Sopenharmony_ci	 * Round up to the next @c->max_write_size boundary i.e. @offs is in
4098c2ecf20Sopenharmony_ci	 * the last wbuf written. After that should be empty space.
4108c2ecf20Sopenharmony_ci	 */
4118c2ecf20Sopenharmony_ci	empty_offs = ALIGN(offs + 1, c->max_write_size);
4128c2ecf20Sopenharmony_ci	check_len = c->leb_size - empty_offs;
4138c2ecf20Sopenharmony_ci	p = buf + empty_offs - offs;
4148c2ecf20Sopenharmony_ci	return is_empty(p, check_len);
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci/**
4188c2ecf20Sopenharmony_ci * clean_buf - clean the data from an LEB sitting in a buffer.
4198c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4208c2ecf20Sopenharmony_ci * @buf: buffer to clean
4218c2ecf20Sopenharmony_ci * @lnum: LEB number to clean
4228c2ecf20Sopenharmony_ci * @offs: offset from which to clean
4238c2ecf20Sopenharmony_ci * @len: length of buffer
4248c2ecf20Sopenharmony_ci *
4258c2ecf20Sopenharmony_ci * This function pads up to the next min_io_size boundary (if there is one) and
4268c2ecf20Sopenharmony_ci * sets empty space to all 0xff. @buf, @offs and @len are updated to the next
4278c2ecf20Sopenharmony_ci * @c->min_io_size boundary.
4288c2ecf20Sopenharmony_ci */
4298c2ecf20Sopenharmony_cistatic void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
4308c2ecf20Sopenharmony_ci		      int *offs, int *len)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	int empty_offs, pad_len;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	ubifs_assert(c, !(*offs & 7));
4378c2ecf20Sopenharmony_ci	empty_offs = ALIGN(*offs, c->min_io_size);
4388c2ecf20Sopenharmony_ci	pad_len = empty_offs - *offs;
4398c2ecf20Sopenharmony_ci	ubifs_pad(c, *buf, pad_len);
4408c2ecf20Sopenharmony_ci	*offs += pad_len;
4418c2ecf20Sopenharmony_ci	*buf += pad_len;
4428c2ecf20Sopenharmony_ci	*len -= pad_len;
4438c2ecf20Sopenharmony_ci	memset(*buf, 0xff, c->leb_size - empty_offs);
4448c2ecf20Sopenharmony_ci}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci/**
4478c2ecf20Sopenharmony_ci * no_more_nodes - determine if there are no more nodes in a buffer.
4488c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4498c2ecf20Sopenharmony_ci * @buf: buffer to check
4508c2ecf20Sopenharmony_ci * @len: length of buffer
4518c2ecf20Sopenharmony_ci * @lnum: LEB number of the LEB from which @buf was read
4528c2ecf20Sopenharmony_ci * @offs: offset from which @buf was read
4538c2ecf20Sopenharmony_ci *
4548c2ecf20Sopenharmony_ci * This function ensures that the corrupted node at @offs is the last thing
4558c2ecf20Sopenharmony_ci * written to a LEB. This function returns %1 if more data is not found and
4568c2ecf20Sopenharmony_ci * %0 if more data is found.
4578c2ecf20Sopenharmony_ci */
4588c2ecf20Sopenharmony_cistatic int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
4598c2ecf20Sopenharmony_ci			int lnum, int offs)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = buf;
4628c2ecf20Sopenharmony_ci	int skip, dlen = le32_to_cpu(ch->len);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	/* Check for empty space after the corrupt node's common header */
4658c2ecf20Sopenharmony_ci	skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs;
4668c2ecf20Sopenharmony_ci	if (is_empty(buf + skip, len - skip))
4678c2ecf20Sopenharmony_ci		return 1;
4688c2ecf20Sopenharmony_ci	/*
4698c2ecf20Sopenharmony_ci	 * The area after the common header size is not empty, so the common
4708c2ecf20Sopenharmony_ci	 * header must be intact. Check it.
4718c2ecf20Sopenharmony_ci	 */
4728c2ecf20Sopenharmony_ci	if (ubifs_check_node(c, buf, len, lnum, offs, 1, 0) != -EUCLEAN) {
4738c2ecf20Sopenharmony_ci		dbg_rcvry("unexpected bad common header at %d:%d", lnum, offs);
4748c2ecf20Sopenharmony_ci		return 0;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci	/* Now we know the corrupt node's length we can skip over it */
4778c2ecf20Sopenharmony_ci	skip = ALIGN(offs + dlen, c->max_write_size) - offs;
4788c2ecf20Sopenharmony_ci	/* After which there should be empty space */
4798c2ecf20Sopenharmony_ci	if (is_empty(buf + skip, len - skip))
4808c2ecf20Sopenharmony_ci		return 1;
4818c2ecf20Sopenharmony_ci	dbg_rcvry("unexpected data at %d:%d", lnum, offs + skip);
4828c2ecf20Sopenharmony_ci	return 0;
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci/**
4868c2ecf20Sopenharmony_ci * fix_unclean_leb - fix an unclean LEB.
4878c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4888c2ecf20Sopenharmony_ci * @sleb: scanned LEB information
4898c2ecf20Sopenharmony_ci * @start: offset where scan started
4908c2ecf20Sopenharmony_ci */
4918c2ecf20Sopenharmony_cistatic int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
4928c2ecf20Sopenharmony_ci			   int start)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	int lnum = sleb->lnum, endpt = start;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	/* Get the end offset of the last node we are keeping */
4978c2ecf20Sopenharmony_ci	if (!list_empty(&sleb->nodes)) {
4988c2ecf20Sopenharmony_ci		struct ubifs_scan_node *snod;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci		snod = list_entry(sleb->nodes.prev,
5018c2ecf20Sopenharmony_ci				  struct ubifs_scan_node, list);
5028c2ecf20Sopenharmony_ci		endpt = snod->offs + snod->len;
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (c->ro_mount && !c->remounting_rw) {
5068c2ecf20Sopenharmony_ci		/* Add to recovery list */
5078c2ecf20Sopenharmony_ci		struct ubifs_unclean_leb *ucleb;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		dbg_rcvry("need to fix LEB %d start %d endpt %d",
5108c2ecf20Sopenharmony_ci			  lnum, start, sleb->endpt);
5118c2ecf20Sopenharmony_ci		ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS);
5128c2ecf20Sopenharmony_ci		if (!ucleb)
5138c2ecf20Sopenharmony_ci			return -ENOMEM;
5148c2ecf20Sopenharmony_ci		ucleb->lnum = lnum;
5158c2ecf20Sopenharmony_ci		ucleb->endpt = endpt;
5168c2ecf20Sopenharmony_ci		list_add_tail(&ucleb->list, &c->unclean_leb_list);
5178c2ecf20Sopenharmony_ci	} else {
5188c2ecf20Sopenharmony_ci		/* Write the fixed LEB back to flash */
5198c2ecf20Sopenharmony_ci		int err;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci		dbg_rcvry("fixing LEB %d start %d endpt %d",
5228c2ecf20Sopenharmony_ci			  lnum, start, sleb->endpt);
5238c2ecf20Sopenharmony_ci		if (endpt == 0) {
5248c2ecf20Sopenharmony_ci			err = ubifs_leb_unmap(c, lnum);
5258c2ecf20Sopenharmony_ci			if (err)
5268c2ecf20Sopenharmony_ci				return err;
5278c2ecf20Sopenharmony_ci		} else {
5288c2ecf20Sopenharmony_ci			int len = ALIGN(endpt, c->min_io_size);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci			if (start) {
5318c2ecf20Sopenharmony_ci				err = ubifs_leb_read(c, lnum, sleb->buf, 0,
5328c2ecf20Sopenharmony_ci						     start, 1);
5338c2ecf20Sopenharmony_ci				if (err)
5348c2ecf20Sopenharmony_ci					return err;
5358c2ecf20Sopenharmony_ci			}
5368c2ecf20Sopenharmony_ci			/* Pad to min_io_size */
5378c2ecf20Sopenharmony_ci			if (len > endpt) {
5388c2ecf20Sopenharmony_ci				int pad_len = len - ALIGN(endpt, 8);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci				if (pad_len > 0) {
5418c2ecf20Sopenharmony_ci					void *buf = sleb->buf + len - pad_len;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci					ubifs_pad(c, buf, pad_len);
5448c2ecf20Sopenharmony_ci				}
5458c2ecf20Sopenharmony_ci			}
5468c2ecf20Sopenharmony_ci			err = ubifs_leb_change(c, lnum, sleb->buf, len);
5478c2ecf20Sopenharmony_ci			if (err)
5488c2ecf20Sopenharmony_ci				return err;
5498c2ecf20Sopenharmony_ci		}
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci	return 0;
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci/**
5558c2ecf20Sopenharmony_ci * drop_last_group - drop the last group of nodes.
5568c2ecf20Sopenharmony_ci * @sleb: scanned LEB information
5578c2ecf20Sopenharmony_ci * @offs: offset of dropped nodes is returned here
5588c2ecf20Sopenharmony_ci *
5598c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last
5608c2ecf20Sopenharmony_ci * group of nodes of the scanned LEB.
5618c2ecf20Sopenharmony_ci */
5628c2ecf20Sopenharmony_cistatic void drop_last_group(struct ubifs_scan_leb *sleb, int *offs)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	while (!list_empty(&sleb->nodes)) {
5658c2ecf20Sopenharmony_ci		struct ubifs_scan_node *snod;
5668c2ecf20Sopenharmony_ci		struct ubifs_ch *ch;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
5698c2ecf20Sopenharmony_ci				  list);
5708c2ecf20Sopenharmony_ci		ch = snod->node;
5718c2ecf20Sopenharmony_ci		if (ch->group_type != UBIFS_IN_NODE_GROUP)
5728c2ecf20Sopenharmony_ci			break;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci		dbg_rcvry("dropping grouped node at %d:%d",
5758c2ecf20Sopenharmony_ci			  sleb->lnum, snod->offs);
5768c2ecf20Sopenharmony_ci		*offs = snod->offs;
5778c2ecf20Sopenharmony_ci		list_del(&snod->list);
5788c2ecf20Sopenharmony_ci		kfree(snod);
5798c2ecf20Sopenharmony_ci		sleb->nodes_cnt -= 1;
5808c2ecf20Sopenharmony_ci	}
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci/**
5848c2ecf20Sopenharmony_ci * drop_last_node - drop the last node.
5858c2ecf20Sopenharmony_ci * @sleb: scanned LEB information
5868c2ecf20Sopenharmony_ci * @offs: offset of dropped nodes is returned here
5878c2ecf20Sopenharmony_ci *
5888c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last
5898c2ecf20Sopenharmony_ci * node of the scanned LEB.
5908c2ecf20Sopenharmony_ci */
5918c2ecf20Sopenharmony_cistatic void drop_last_node(struct ubifs_scan_leb *sleb, int *offs)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	struct ubifs_scan_node *snod;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (!list_empty(&sleb->nodes)) {
5968c2ecf20Sopenharmony_ci		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
5978c2ecf20Sopenharmony_ci				  list);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci		dbg_rcvry("dropping last node at %d:%d",
6008c2ecf20Sopenharmony_ci			  sleb->lnum, snod->offs);
6018c2ecf20Sopenharmony_ci		*offs = snod->offs;
6028c2ecf20Sopenharmony_ci		list_del(&snod->list);
6038c2ecf20Sopenharmony_ci		kfree(snod);
6048c2ecf20Sopenharmony_ci		sleb->nodes_cnt -= 1;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci/**
6098c2ecf20Sopenharmony_ci * ubifs_recover_leb - scan and recover a LEB.
6108c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
6118c2ecf20Sopenharmony_ci * @lnum: LEB number
6128c2ecf20Sopenharmony_ci * @offs: offset
6138c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
6148c2ecf20Sopenharmony_ci * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not
6158c2ecf20Sopenharmony_ci *         belong to any journal head)
6168c2ecf20Sopenharmony_ci *
6178c2ecf20Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have
6188c2ecf20Sopenharmony_ci * been caused by the unclean unmount from which we are attempting to recover.
6198c2ecf20Sopenharmony_ci * Returns the scanned information on success and a negative error code on
6208c2ecf20Sopenharmony_ci * failure.
6218c2ecf20Sopenharmony_ci */
6228c2ecf20Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
6238c2ecf20Sopenharmony_ci					 int offs, void *sbuf, int jhead)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit;
6268c2ecf20Sopenharmony_ci	int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped;
6278c2ecf20Sopenharmony_ci	struct ubifs_scan_leb *sleb;
6288c2ecf20Sopenharmony_ci	void *buf = sbuf + offs;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	sleb = ubifs_start_scan(c, lnum, offs, sbuf);
6338c2ecf20Sopenharmony_ci	if (IS_ERR(sleb))
6348c2ecf20Sopenharmony_ci		return sleb;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	ubifs_assert(c, len >= 8);
6378c2ecf20Sopenharmony_ci	while (len >= 8) {
6388c2ecf20Sopenharmony_ci		dbg_scan("look at LEB %d:%d (%d bytes left)",
6398c2ecf20Sopenharmony_ci			 lnum, offs, len);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci		cond_resched();
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci		/*
6448c2ecf20Sopenharmony_ci		 * Scan quietly until there is an error from which we cannot
6458c2ecf20Sopenharmony_ci		 * recover
6468c2ecf20Sopenharmony_ci		 */
6478c2ecf20Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
6488c2ecf20Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
6498c2ecf20Sopenharmony_ci			/* A valid node, and not a padding node */
6508c2ecf20Sopenharmony_ci			struct ubifs_ch *ch = buf;
6518c2ecf20Sopenharmony_ci			int node_len;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci			err = ubifs_add_snod(c, sleb, buf, offs);
6548c2ecf20Sopenharmony_ci			if (err)
6558c2ecf20Sopenharmony_ci				goto error;
6568c2ecf20Sopenharmony_ci			node_len = ALIGN(le32_to_cpu(ch->len), 8);
6578c2ecf20Sopenharmony_ci			offs += node_len;
6588c2ecf20Sopenharmony_ci			buf += node_len;
6598c2ecf20Sopenharmony_ci			len -= node_len;
6608c2ecf20Sopenharmony_ci		} else if (ret > 0) {
6618c2ecf20Sopenharmony_ci			/* Padding bytes or a valid padding node */
6628c2ecf20Sopenharmony_ci			offs += ret;
6638c2ecf20Sopenharmony_ci			buf += ret;
6648c2ecf20Sopenharmony_ci			len -= ret;
6658c2ecf20Sopenharmony_ci		} else if (ret == SCANNED_EMPTY_SPACE ||
6668c2ecf20Sopenharmony_ci			   ret == SCANNED_GARBAGE     ||
6678c2ecf20Sopenharmony_ci			   ret == SCANNED_A_BAD_PAD_NODE ||
6688c2ecf20Sopenharmony_ci			   ret == SCANNED_A_CORRUPT_NODE) {
6698c2ecf20Sopenharmony_ci			dbg_rcvry("found corruption (%d) at %d:%d",
6708c2ecf20Sopenharmony_ci				  ret, lnum, offs);
6718c2ecf20Sopenharmony_ci			break;
6728c2ecf20Sopenharmony_ci		} else {
6738c2ecf20Sopenharmony_ci			ubifs_err(c, "unexpected return value %d", ret);
6748c2ecf20Sopenharmony_ci			err = -EINVAL;
6758c2ecf20Sopenharmony_ci			goto error;
6768c2ecf20Sopenharmony_ci		}
6778c2ecf20Sopenharmony_ci	}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE) {
6808c2ecf20Sopenharmony_ci		if (!is_last_write(c, buf, offs))
6818c2ecf20Sopenharmony_ci			goto corrupted_rescan;
6828c2ecf20Sopenharmony_ci	} else if (ret == SCANNED_A_CORRUPT_NODE) {
6838c2ecf20Sopenharmony_ci		if (!no_more_nodes(c, buf, len, lnum, offs))
6848c2ecf20Sopenharmony_ci			goto corrupted_rescan;
6858c2ecf20Sopenharmony_ci	} else if (!is_empty(buf, len)) {
6868c2ecf20Sopenharmony_ci		if (!is_last_write(c, buf, offs)) {
6878c2ecf20Sopenharmony_ci			int corruption = first_non_ff(buf, len);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci			/*
6908c2ecf20Sopenharmony_ci			 * See header comment for this file for more
6918c2ecf20Sopenharmony_ci			 * explanations about the reasons we have this check.
6928c2ecf20Sopenharmony_ci			 */
6938c2ecf20Sopenharmony_ci			ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d",
6948c2ecf20Sopenharmony_ci				  lnum, offs, corruption);
6958c2ecf20Sopenharmony_ci			/* Make sure we dump interesting non-0xFF data */
6968c2ecf20Sopenharmony_ci			offs += corruption;
6978c2ecf20Sopenharmony_ci			buf += corruption;
6988c2ecf20Sopenharmony_ci			goto corrupted;
6998c2ecf20Sopenharmony_ci		}
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	min_io_unit = round_down(offs, c->min_io_size);
7038c2ecf20Sopenharmony_ci	if (grouped)
7048c2ecf20Sopenharmony_ci		/*
7058c2ecf20Sopenharmony_ci		 * If nodes are grouped, always drop the incomplete group at
7068c2ecf20Sopenharmony_ci		 * the end.
7078c2ecf20Sopenharmony_ci		 */
7088c2ecf20Sopenharmony_ci		drop_last_group(sleb, &offs);
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (jhead == GCHD) {
7118c2ecf20Sopenharmony_ci		/*
7128c2ecf20Sopenharmony_ci		 * If this LEB belongs to the GC head then while we are in the
7138c2ecf20Sopenharmony_ci		 * middle of the same min. I/O unit keep dropping nodes. So
7148c2ecf20Sopenharmony_ci		 * basically, what we want is to make sure that the last min.
7158c2ecf20Sopenharmony_ci		 * I/O unit where we saw the corruption is dropped completely
7168c2ecf20Sopenharmony_ci		 * with all the uncorrupted nodes which may possibly sit there.
7178c2ecf20Sopenharmony_ci		 *
7188c2ecf20Sopenharmony_ci		 * In other words, let's name the min. I/O unit where the
7198c2ecf20Sopenharmony_ci		 * corruption starts B, and the previous min. I/O unit A. The
7208c2ecf20Sopenharmony_ci		 * below code tries to deal with a situation when half of B
7218c2ecf20Sopenharmony_ci		 * contains valid nodes or the end of a valid node, and the
7228c2ecf20Sopenharmony_ci		 * second half of B contains corrupted data or garbage. This
7238c2ecf20Sopenharmony_ci		 * means that UBIFS had been writing to B just before the power
7248c2ecf20Sopenharmony_ci		 * cut happened. I do not know how realistic is this scenario
7258c2ecf20Sopenharmony_ci		 * that half of the min. I/O unit had been written successfully
7268c2ecf20Sopenharmony_ci		 * and the other half not, but this is possible in our 'failure
7278c2ecf20Sopenharmony_ci		 * mode emulation' infrastructure at least.
7288c2ecf20Sopenharmony_ci		 *
7298c2ecf20Sopenharmony_ci		 * So what is the problem, why we need to drop those nodes? Why
7308c2ecf20Sopenharmony_ci		 * can't we just clean-up the second half of B by putting a
7318c2ecf20Sopenharmony_ci		 * padding node there? We can, and this works fine with one
7328c2ecf20Sopenharmony_ci		 * exception which was reproduced with power cut emulation
7338c2ecf20Sopenharmony_ci		 * testing and happens extremely rarely.
7348c2ecf20Sopenharmony_ci		 *
7358c2ecf20Sopenharmony_ci		 * Imagine the file-system is full, we run GC which starts
7368c2ecf20Sopenharmony_ci		 * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is
7378c2ecf20Sopenharmony_ci		 * the current GC head LEB). The @c->gc_lnum is -1, which means
7388c2ecf20Sopenharmony_ci		 * that GC will retain LEB X and will try to continue. Imagine
7398c2ecf20Sopenharmony_ci		 * that LEB X is currently the dirtiest LEB, and the amount of
7408c2ecf20Sopenharmony_ci		 * used space in LEB Y is exactly the same as amount of free
7418c2ecf20Sopenharmony_ci		 * space in LEB X.
7428c2ecf20Sopenharmony_ci		 *
7438c2ecf20Sopenharmony_ci		 * And a power cut happens when nodes are moved from LEB X to
7448c2ecf20Sopenharmony_ci		 * LEB Y. We are here trying to recover LEB Y which is the GC
7458c2ecf20Sopenharmony_ci		 * head LEB. We find the min. I/O unit B as described above.
7468c2ecf20Sopenharmony_ci		 * Then we clean-up LEB Y by padding min. I/O unit. And later
7478c2ecf20Sopenharmony_ci		 * 'ubifs_rcvry_gc_commit()' function fails, because it cannot
7488c2ecf20Sopenharmony_ci		 * find a dirty LEB which could be GC'd into LEB Y! Even LEB X
7498c2ecf20Sopenharmony_ci		 * does not match because the amount of valid nodes there does
7508c2ecf20Sopenharmony_ci		 * not fit the free space in LEB Y any more! And this is
7518c2ecf20Sopenharmony_ci		 * because of the padding node which we added to LEB Y. The
7528c2ecf20Sopenharmony_ci		 * user-visible effect of this which I once observed and
7538c2ecf20Sopenharmony_ci		 * analysed is that we cannot mount the file-system with
7548c2ecf20Sopenharmony_ci		 * -ENOSPC error.
7558c2ecf20Sopenharmony_ci		 *
7568c2ecf20Sopenharmony_ci		 * So obviously, to make sure that situation does not happen we
7578c2ecf20Sopenharmony_ci		 * should free min. I/O unit B in LEB Y completely and the last
7588c2ecf20Sopenharmony_ci		 * used min. I/O unit in LEB Y should be A. This is basically
7598c2ecf20Sopenharmony_ci		 * what the below code tries to do.
7608c2ecf20Sopenharmony_ci		 */
7618c2ecf20Sopenharmony_ci		while (offs > min_io_unit)
7628c2ecf20Sopenharmony_ci			drop_last_node(sleb, &offs);
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	buf = sbuf + offs;
7668c2ecf20Sopenharmony_ci	len = c->leb_size - offs;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	clean_buf(c, &buf, lnum, &offs, &len);
7698c2ecf20Sopenharmony_ci	ubifs_end_scan(c, sleb, lnum, offs);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	err = fix_unclean_leb(c, sleb, start);
7728c2ecf20Sopenharmony_ci	if (err)
7738c2ecf20Sopenharmony_ci		goto error;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	return sleb;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_cicorrupted_rescan:
7788c2ecf20Sopenharmony_ci	/* Re-scan the corrupted data with verbose messages */
7798c2ecf20Sopenharmony_ci	ubifs_err(c, "corruption %d", ret);
7808c2ecf20Sopenharmony_ci	ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
7818c2ecf20Sopenharmony_cicorrupted:
7828c2ecf20Sopenharmony_ci	ubifs_scanned_corruption(c, lnum, offs, buf);
7838c2ecf20Sopenharmony_ci	err = -EUCLEAN;
7848c2ecf20Sopenharmony_cierror:
7858c2ecf20Sopenharmony_ci	ubifs_err(c, "LEB %d scanning failed", lnum);
7868c2ecf20Sopenharmony_ci	ubifs_scan_destroy(sleb);
7878c2ecf20Sopenharmony_ci	return ERR_PTR(err);
7888c2ecf20Sopenharmony_ci}
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci/**
7918c2ecf20Sopenharmony_ci * get_cs_sqnum - get commit start sequence number.
7928c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
7938c2ecf20Sopenharmony_ci * @lnum: LEB number of commit start node
7948c2ecf20Sopenharmony_ci * @offs: offset of commit start node
7958c2ecf20Sopenharmony_ci * @cs_sqnum: commit start sequence number is returned here
7968c2ecf20Sopenharmony_ci *
7978c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
7988c2ecf20Sopenharmony_ci */
7998c2ecf20Sopenharmony_cistatic int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
8008c2ecf20Sopenharmony_ci			unsigned long long *cs_sqnum)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct ubifs_cs_node *cs_node = NULL;
8038c2ecf20Sopenharmony_ci	int err, ret;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	dbg_rcvry("at %d:%d", lnum, offs);
8068c2ecf20Sopenharmony_ci	cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL);
8078c2ecf20Sopenharmony_ci	if (!cs_node)
8088c2ecf20Sopenharmony_ci		return -ENOMEM;
8098c2ecf20Sopenharmony_ci	if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
8108c2ecf20Sopenharmony_ci		goto out_err;
8118c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
8128c2ecf20Sopenharmony_ci			     UBIFS_CS_NODE_SZ, 0);
8138c2ecf20Sopenharmony_ci	if (err && err != -EBADMSG)
8148c2ecf20Sopenharmony_ci		goto out_free;
8158c2ecf20Sopenharmony_ci	ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
8168c2ecf20Sopenharmony_ci	if (ret != SCANNED_A_NODE) {
8178c2ecf20Sopenharmony_ci		ubifs_err(c, "Not a valid node");
8188c2ecf20Sopenharmony_ci		goto out_err;
8198c2ecf20Sopenharmony_ci	}
8208c2ecf20Sopenharmony_ci	if (cs_node->ch.node_type != UBIFS_CS_NODE) {
8218c2ecf20Sopenharmony_ci		ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type);
8228c2ecf20Sopenharmony_ci		goto out_err;
8238c2ecf20Sopenharmony_ci	}
8248c2ecf20Sopenharmony_ci	if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
8258c2ecf20Sopenharmony_ci		ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu",
8268c2ecf20Sopenharmony_ci			  (unsigned long long)le64_to_cpu(cs_node->cmt_no),
8278c2ecf20Sopenharmony_ci			  c->cmt_no);
8288c2ecf20Sopenharmony_ci		goto out_err;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci	*cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
8318c2ecf20Sopenharmony_ci	dbg_rcvry("commit start sqnum %llu", *cs_sqnum);
8328c2ecf20Sopenharmony_ci	kfree(cs_node);
8338c2ecf20Sopenharmony_ci	return 0;
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ciout_err:
8368c2ecf20Sopenharmony_ci	err = -EINVAL;
8378c2ecf20Sopenharmony_ciout_free:
8388c2ecf20Sopenharmony_ci	ubifs_err(c, "failed to get CS sqnum");
8398c2ecf20Sopenharmony_ci	kfree(cs_node);
8408c2ecf20Sopenharmony_ci	return err;
8418c2ecf20Sopenharmony_ci}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci/**
8448c2ecf20Sopenharmony_ci * ubifs_recover_log_leb - scan and recover a log LEB.
8458c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
8468c2ecf20Sopenharmony_ci * @lnum: LEB number
8478c2ecf20Sopenharmony_ci * @offs: offset
8488c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
8498c2ecf20Sopenharmony_ci *
8508c2ecf20Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have
8518c2ecf20Sopenharmony_ci * been caused by unclean reboots from which we are attempting to recover
8528c2ecf20Sopenharmony_ci * (assume that only the last log LEB can be corrupted by an unclean reboot).
8538c2ecf20Sopenharmony_ci *
8548c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
8558c2ecf20Sopenharmony_ci */
8568c2ecf20Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
8578c2ecf20Sopenharmony_ci					     int offs, void *sbuf)
8588c2ecf20Sopenharmony_ci{
8598c2ecf20Sopenharmony_ci	struct ubifs_scan_leb *sleb;
8608c2ecf20Sopenharmony_ci	int next_lnum;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	dbg_rcvry("LEB %d", lnum);
8638c2ecf20Sopenharmony_ci	next_lnum = lnum + 1;
8648c2ecf20Sopenharmony_ci	if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs)
8658c2ecf20Sopenharmony_ci		next_lnum = UBIFS_LOG_LNUM;
8668c2ecf20Sopenharmony_ci	if (next_lnum != c->ltail_lnum) {
8678c2ecf20Sopenharmony_ci		/*
8688c2ecf20Sopenharmony_ci		 * We can only recover at the end of the log, so check that the
8698c2ecf20Sopenharmony_ci		 * next log LEB is empty or out of date.
8708c2ecf20Sopenharmony_ci		 */
8718c2ecf20Sopenharmony_ci		sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0);
8728c2ecf20Sopenharmony_ci		if (IS_ERR(sleb))
8738c2ecf20Sopenharmony_ci			return sleb;
8748c2ecf20Sopenharmony_ci		if (sleb->nodes_cnt) {
8758c2ecf20Sopenharmony_ci			struct ubifs_scan_node *snod;
8768c2ecf20Sopenharmony_ci			unsigned long long cs_sqnum = c->cs_sqnum;
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci			snod = list_entry(sleb->nodes.next,
8798c2ecf20Sopenharmony_ci					  struct ubifs_scan_node, list);
8808c2ecf20Sopenharmony_ci			if (cs_sqnum == 0) {
8818c2ecf20Sopenharmony_ci				int err;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci				err = get_cs_sqnum(c, lnum, offs, &cs_sqnum);
8848c2ecf20Sopenharmony_ci				if (err) {
8858c2ecf20Sopenharmony_ci					ubifs_scan_destroy(sleb);
8868c2ecf20Sopenharmony_ci					return ERR_PTR(err);
8878c2ecf20Sopenharmony_ci				}
8888c2ecf20Sopenharmony_ci			}
8898c2ecf20Sopenharmony_ci			if (snod->sqnum > cs_sqnum) {
8908c2ecf20Sopenharmony_ci				ubifs_err(c, "unrecoverable log corruption in LEB %d",
8918c2ecf20Sopenharmony_ci					  lnum);
8928c2ecf20Sopenharmony_ci				ubifs_scan_destroy(sleb);
8938c2ecf20Sopenharmony_ci				return ERR_PTR(-EUCLEAN);
8948c2ecf20Sopenharmony_ci			}
8958c2ecf20Sopenharmony_ci		}
8968c2ecf20Sopenharmony_ci		ubifs_scan_destroy(sleb);
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci	return ubifs_recover_leb(c, lnum, offs, sbuf, -1);
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci/**
9028c2ecf20Sopenharmony_ci * recover_head - recover a head.
9038c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9048c2ecf20Sopenharmony_ci * @lnum: LEB number of head to recover
9058c2ecf20Sopenharmony_ci * @offs: offset of head to recover
9068c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
9078c2ecf20Sopenharmony_ci *
9088c2ecf20Sopenharmony_ci * This function ensures that there is no data on the flash at a head location.
9098c2ecf20Sopenharmony_ci *
9108c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
9118c2ecf20Sopenharmony_ci */
9128c2ecf20Sopenharmony_cistatic int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci	int len = c->max_write_size, err;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	if (offs + len > c->leb_size)
9178c2ecf20Sopenharmony_ci		len = c->leb_size - offs;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	if (!len)
9208c2ecf20Sopenharmony_ci		return 0;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	/* Read at the head location and check it is empty flash */
9238c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
9248c2ecf20Sopenharmony_ci	if (err || !is_empty(sbuf, len)) {
9258c2ecf20Sopenharmony_ci		dbg_rcvry("cleaning head at %d:%d", lnum, offs);
9268c2ecf20Sopenharmony_ci		if (offs == 0)
9278c2ecf20Sopenharmony_ci			return ubifs_leb_unmap(c, lnum);
9288c2ecf20Sopenharmony_ci		err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
9298c2ecf20Sopenharmony_ci		if (err)
9308c2ecf20Sopenharmony_ci			return err;
9318c2ecf20Sopenharmony_ci		return ubifs_leb_change(c, lnum, sbuf, offs);
9328c2ecf20Sopenharmony_ci	}
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	return 0;
9358c2ecf20Sopenharmony_ci}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci/**
9388c2ecf20Sopenharmony_ci * ubifs_recover_inl_heads - recover index and LPT heads.
9398c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9408c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
9418c2ecf20Sopenharmony_ci *
9428c2ecf20Sopenharmony_ci * This function ensures that there is no data on the flash at the index and
9438c2ecf20Sopenharmony_ci * LPT head locations.
9448c2ecf20Sopenharmony_ci *
9458c2ecf20Sopenharmony_ci * This deals with the recovery of a half-completed journal commit. UBIFS is
9468c2ecf20Sopenharmony_ci * careful never to overwrite the last version of the index or the LPT. Because
9478c2ecf20Sopenharmony_ci * the index and LPT are wandering trees, data from a half-completed commit will
9488c2ecf20Sopenharmony_ci * not be referenced anywhere in UBIFS. The data will be either in LEBs that are
9498c2ecf20Sopenharmony_ci * assumed to be empty and will be unmapped anyway before use, or in the index
9508c2ecf20Sopenharmony_ci * and LPT heads.
9518c2ecf20Sopenharmony_ci *
9528c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
9538c2ecf20Sopenharmony_ci */
9548c2ecf20Sopenharmony_ciint ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci	int err;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_mount || c->remounting_rw);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
9618c2ecf20Sopenharmony_ci	err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
9628c2ecf20Sopenharmony_ci	if (err)
9638c2ecf20Sopenharmony_ci		return err;
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
9688c2ecf20Sopenharmony_ci}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci/**
9718c2ecf20Sopenharmony_ci * clean_an_unclean_leb - read and write a LEB to remove corruption.
9728c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9738c2ecf20Sopenharmony_ci * @ucleb: unclean LEB information
9748c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
9758c2ecf20Sopenharmony_ci *
9768c2ecf20Sopenharmony_ci * This function reads a LEB up to a point pre-determined by the mount recovery,
9778c2ecf20Sopenharmony_ci * checks the nodes, and writes the result back to the flash, thereby cleaning
9788c2ecf20Sopenharmony_ci * off any following corruption, or non-fatal ECC errors.
9798c2ecf20Sopenharmony_ci *
9808c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
9818c2ecf20Sopenharmony_ci */
9828c2ecf20Sopenharmony_cistatic int clean_an_unclean_leb(struct ubifs_info *c,
9838c2ecf20Sopenharmony_ci				struct ubifs_unclean_leb *ucleb, void *sbuf)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
9868c2ecf20Sopenharmony_ci	void *buf = sbuf;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	dbg_rcvry("LEB %d len %d", lnum, len);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	if (len == 0) {
9918c2ecf20Sopenharmony_ci		/* Nothing to read, just unmap it */
9928c2ecf20Sopenharmony_ci		return ubifs_leb_unmap(c, lnum);
9938c2ecf20Sopenharmony_ci	}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
9968c2ecf20Sopenharmony_ci	if (err && err != -EBADMSG)
9978c2ecf20Sopenharmony_ci		return err;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	while (len >= 8) {
10008c2ecf20Sopenharmony_ci		int ret;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci		cond_resched();
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		/* Scan quietly until there is an error */
10058c2ecf20Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
10088c2ecf20Sopenharmony_ci			/* A valid node, and not a padding node */
10098c2ecf20Sopenharmony_ci			struct ubifs_ch *ch = buf;
10108c2ecf20Sopenharmony_ci			int node_len;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci			node_len = ALIGN(le32_to_cpu(ch->len), 8);
10138c2ecf20Sopenharmony_ci			offs += node_len;
10148c2ecf20Sopenharmony_ci			buf += node_len;
10158c2ecf20Sopenharmony_ci			len -= node_len;
10168c2ecf20Sopenharmony_ci			continue;
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci		if (ret > 0) {
10208c2ecf20Sopenharmony_ci			/* Padding bytes or a valid padding node */
10218c2ecf20Sopenharmony_ci			offs += ret;
10228c2ecf20Sopenharmony_ci			buf += ret;
10238c2ecf20Sopenharmony_ci			len -= ret;
10248c2ecf20Sopenharmony_ci			continue;
10258c2ecf20Sopenharmony_ci		}
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci		if (ret == SCANNED_EMPTY_SPACE) {
10288c2ecf20Sopenharmony_ci			ubifs_err(c, "unexpected empty space at %d:%d",
10298c2ecf20Sopenharmony_ci				  lnum, offs);
10308c2ecf20Sopenharmony_ci			return -EUCLEAN;
10318c2ecf20Sopenharmony_ci		}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci		if (quiet) {
10348c2ecf20Sopenharmony_ci			/* Redo the last scan but noisily */
10358c2ecf20Sopenharmony_ci			quiet = 0;
10368c2ecf20Sopenharmony_ci			continue;
10378c2ecf20Sopenharmony_ci		}
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci		ubifs_scanned_corruption(c, lnum, offs, buf);
10408c2ecf20Sopenharmony_ci		return -EUCLEAN;
10418c2ecf20Sopenharmony_ci	}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	/* Pad to min_io_size */
10448c2ecf20Sopenharmony_ci	len = ALIGN(ucleb->endpt, c->min_io_size);
10458c2ecf20Sopenharmony_ci	if (len > ucleb->endpt) {
10468c2ecf20Sopenharmony_ci		int pad_len = len - ALIGN(ucleb->endpt, 8);
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci		if (pad_len > 0) {
10498c2ecf20Sopenharmony_ci			buf = c->sbuf + len - pad_len;
10508c2ecf20Sopenharmony_ci			ubifs_pad(c, buf, pad_len);
10518c2ecf20Sopenharmony_ci		}
10528c2ecf20Sopenharmony_ci	}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	/* Write back the LEB atomically */
10558c2ecf20Sopenharmony_ci	err = ubifs_leb_change(c, lnum, sbuf, len);
10568c2ecf20Sopenharmony_ci	if (err)
10578c2ecf20Sopenharmony_ci		return err;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	dbg_rcvry("cleaned LEB %d", lnum);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	return 0;
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci/**
10658c2ecf20Sopenharmony_ci * ubifs_clean_lebs - clean LEBs recovered during read-only mount.
10668c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
10678c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use
10688c2ecf20Sopenharmony_ci *
10698c2ecf20Sopenharmony_ci * This function cleans a LEB identified during recovery that needs to be
10708c2ecf20Sopenharmony_ci * written but was not because UBIFS was mounted read-only. This happens when
10718c2ecf20Sopenharmony_ci * remounting to read-write mode.
10728c2ecf20Sopenharmony_ci *
10738c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
10748c2ecf20Sopenharmony_ci */
10758c2ecf20Sopenharmony_ciint ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	dbg_rcvry("recovery");
10788c2ecf20Sopenharmony_ci	while (!list_empty(&c->unclean_leb_list)) {
10798c2ecf20Sopenharmony_ci		struct ubifs_unclean_leb *ucleb;
10808c2ecf20Sopenharmony_ci		int err;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci		ucleb = list_entry(c->unclean_leb_list.next,
10838c2ecf20Sopenharmony_ci				   struct ubifs_unclean_leb, list);
10848c2ecf20Sopenharmony_ci		err = clean_an_unclean_leb(c, ucleb, sbuf);
10858c2ecf20Sopenharmony_ci		if (err)
10868c2ecf20Sopenharmony_ci			return err;
10878c2ecf20Sopenharmony_ci		list_del(&ucleb->list);
10888c2ecf20Sopenharmony_ci		kfree(ucleb);
10898c2ecf20Sopenharmony_ci	}
10908c2ecf20Sopenharmony_ci	return 0;
10918c2ecf20Sopenharmony_ci}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci/**
10948c2ecf20Sopenharmony_ci * grab_empty_leb - grab an empty LEB to use as GC LEB and run commit.
10958c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
10968c2ecf20Sopenharmony_ci *
10978c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty
10988c2ecf20Sopenharmony_ci * LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns
10998c2ecf20Sopenharmony_ci * zero in case of success and a negative error code in case of failure.
11008c2ecf20Sopenharmony_ci */
11018c2ecf20Sopenharmony_cistatic int grab_empty_leb(struct ubifs_info *c)
11028c2ecf20Sopenharmony_ci{
11038c2ecf20Sopenharmony_ci	int lnum, err;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	/*
11068c2ecf20Sopenharmony_ci	 * Note, it is very important to first search for an empty LEB and then
11078c2ecf20Sopenharmony_ci	 * run the commit, not vice-versa. The reason is that there might be
11088c2ecf20Sopenharmony_ci	 * only one empty LEB at the moment, the one which has been the
11098c2ecf20Sopenharmony_ci	 * @c->gc_lnum just before the power cut happened. During the regular
11108c2ecf20Sopenharmony_ci	 * UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no
11118c2ecf20Sopenharmony_ci	 * one but GC can grab it. But at this moment this single empty LEB is
11128c2ecf20Sopenharmony_ci	 * not marked as taken, so if we run commit - what happens? Right, the
11138c2ecf20Sopenharmony_ci	 * commit will grab it and write the index there. Remember that the
11148c2ecf20Sopenharmony_ci	 * index always expands as long as there is free space, and it only
11158c2ecf20Sopenharmony_ci	 * starts consolidating when we run out of space.
11168c2ecf20Sopenharmony_ci	 *
11178c2ecf20Sopenharmony_ci	 * IOW, if we run commit now, we might not be able to find a free LEB
11188c2ecf20Sopenharmony_ci	 * after this.
11198c2ecf20Sopenharmony_ci	 */
11208c2ecf20Sopenharmony_ci	lnum = ubifs_find_free_leb_for_idx(c);
11218c2ecf20Sopenharmony_ci	if (lnum < 0) {
11228c2ecf20Sopenharmony_ci		ubifs_err(c, "could not find an empty LEB");
11238c2ecf20Sopenharmony_ci		ubifs_dump_lprops(c);
11248c2ecf20Sopenharmony_ci		ubifs_dump_budg(c, &c->bi);
11258c2ecf20Sopenharmony_ci		return lnum;
11268c2ecf20Sopenharmony_ci	}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/* Reset the index flag */
11298c2ecf20Sopenharmony_ci	err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
11308c2ecf20Sopenharmony_ci				  LPROPS_INDEX, 0);
11318c2ecf20Sopenharmony_ci	if (err)
11328c2ecf20Sopenharmony_ci		return err;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	c->gc_lnum = lnum;
11358c2ecf20Sopenharmony_ci	dbg_rcvry("found empty LEB %d, run commit", lnum);
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	return ubifs_run_commit(c);
11388c2ecf20Sopenharmony_ci}
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci/**
11418c2ecf20Sopenharmony_ci * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit.
11428c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
11438c2ecf20Sopenharmony_ci *
11448c2ecf20Sopenharmony_ci * Out-of-place garbage collection requires always one empty LEB with which to
11458c2ecf20Sopenharmony_ci * start garbage collection. The LEB number is recorded in c->gc_lnum and is
11468c2ecf20Sopenharmony_ci * written to the master node on unmounting. In the case of an unclean unmount
11478c2ecf20Sopenharmony_ci * the value of gc_lnum recorded in the master node is out of date and cannot
11488c2ecf20Sopenharmony_ci * be used. Instead, recovery must allocate an empty LEB for this purpose.
11498c2ecf20Sopenharmony_ci * However, there may not be enough empty space, in which case it must be
11508c2ecf20Sopenharmony_ci * possible to GC the dirtiest LEB into the GC head LEB.
11518c2ecf20Sopenharmony_ci *
11528c2ecf20Sopenharmony_ci * This function also runs the commit which causes the TNC updates from
11538c2ecf20Sopenharmony_ci * size-recovery and orphans to be written to the flash. That is important to
11548c2ecf20Sopenharmony_ci * ensure correct replay order for subsequent mounts.
11558c2ecf20Sopenharmony_ci *
11568c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
11578c2ecf20Sopenharmony_ci */
11588c2ecf20Sopenharmony_ciint ubifs_rcvry_gc_commit(struct ubifs_info *c)
11598c2ecf20Sopenharmony_ci{
11608c2ecf20Sopenharmony_ci	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
11618c2ecf20Sopenharmony_ci	struct ubifs_lprops lp;
11628c2ecf20Sopenharmony_ci	int err;
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	dbg_rcvry("GC head LEB %d, offs %d", wbuf->lnum, wbuf->offs);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	c->gc_lnum = -1;
11678c2ecf20Sopenharmony_ci	if (wbuf->lnum == -1 || wbuf->offs == c->leb_size)
11688c2ecf20Sopenharmony_ci		return grab_empty_leb(c);
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2);
11718c2ecf20Sopenharmony_ci	if (err) {
11728c2ecf20Sopenharmony_ci		if (err != -ENOSPC)
11738c2ecf20Sopenharmony_ci			return err;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci		dbg_rcvry("could not find a dirty LEB");
11768c2ecf20Sopenharmony_ci		return grab_empty_leb(c);
11778c2ecf20Sopenharmony_ci	}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	ubifs_assert(c, !(lp.flags & LPROPS_INDEX));
11808c2ecf20Sopenharmony_ci	ubifs_assert(c, lp.free + lp.dirty >= wbuf->offs);
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	/*
11838c2ecf20Sopenharmony_ci	 * We run the commit before garbage collection otherwise subsequent
11848c2ecf20Sopenharmony_ci	 * mounts will see the GC and orphan deletion in a different order.
11858c2ecf20Sopenharmony_ci	 */
11868c2ecf20Sopenharmony_ci	dbg_rcvry("committing");
11878c2ecf20Sopenharmony_ci	err = ubifs_run_commit(c);
11888c2ecf20Sopenharmony_ci	if (err)
11898c2ecf20Sopenharmony_ci		return err;
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_ci	dbg_rcvry("GC'ing LEB %d", lp.lnum);
11928c2ecf20Sopenharmony_ci	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
11938c2ecf20Sopenharmony_ci	err = ubifs_garbage_collect_leb(c, &lp);
11948c2ecf20Sopenharmony_ci	if (err >= 0) {
11958c2ecf20Sopenharmony_ci		int err2 = ubifs_wbuf_sync_nolock(wbuf);
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci		if (err2)
11988c2ecf20Sopenharmony_ci			err = err2;
11998c2ecf20Sopenharmony_ci	}
12008c2ecf20Sopenharmony_ci	mutex_unlock(&wbuf->io_mutex);
12018c2ecf20Sopenharmony_ci	if (err < 0) {
12028c2ecf20Sopenharmony_ci		ubifs_err(c, "GC failed, error %d", err);
12038c2ecf20Sopenharmony_ci		if (err == -EAGAIN)
12048c2ecf20Sopenharmony_ci			err = -EINVAL;
12058c2ecf20Sopenharmony_ci		return err;
12068c2ecf20Sopenharmony_ci	}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	ubifs_assert(c, err == LEB_RETAINED);
12098c2ecf20Sopenharmony_ci	if (err != LEB_RETAINED)
12108c2ecf20Sopenharmony_ci		return -EINVAL;
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	err = ubifs_leb_unmap(c, c->gc_lnum);
12138c2ecf20Sopenharmony_ci	if (err)
12148c2ecf20Sopenharmony_ci		return err;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	dbg_rcvry("allocated LEB %d for GC", lp.lnum);
12178c2ecf20Sopenharmony_ci	return 0;
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci/**
12218c2ecf20Sopenharmony_ci * struct size_entry - inode size information for recovery.
12228c2ecf20Sopenharmony_ci * @rb: link in the RB-tree of sizes
12238c2ecf20Sopenharmony_ci * @inum: inode number
12248c2ecf20Sopenharmony_ci * @i_size: size on inode
12258c2ecf20Sopenharmony_ci * @d_size: maximum size based on data nodes
12268c2ecf20Sopenharmony_ci * @exists: indicates whether the inode exists
12278c2ecf20Sopenharmony_ci * @inode: inode if pinned in memory awaiting rw mode to fix it
12288c2ecf20Sopenharmony_ci */
12298c2ecf20Sopenharmony_cistruct size_entry {
12308c2ecf20Sopenharmony_ci	struct rb_node rb;
12318c2ecf20Sopenharmony_ci	ino_t inum;
12328c2ecf20Sopenharmony_ci	loff_t i_size;
12338c2ecf20Sopenharmony_ci	loff_t d_size;
12348c2ecf20Sopenharmony_ci	int exists;
12358c2ecf20Sopenharmony_ci	struct inode *inode;
12368c2ecf20Sopenharmony_ci};
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci/**
12398c2ecf20Sopenharmony_ci * add_ino - add an entry to the size tree.
12408c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
12418c2ecf20Sopenharmony_ci * @inum: inode number
12428c2ecf20Sopenharmony_ci * @i_size: size on inode
12438c2ecf20Sopenharmony_ci * @d_size: maximum size based on data nodes
12448c2ecf20Sopenharmony_ci * @exists: indicates whether the inode exists
12458c2ecf20Sopenharmony_ci */
12468c2ecf20Sopenharmony_cistatic int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size,
12478c2ecf20Sopenharmony_ci		   loff_t d_size, int exists)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	struct rb_node **p = &c->size_tree.rb_node, *parent = NULL;
12508c2ecf20Sopenharmony_ci	struct size_entry *e;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	while (*p) {
12538c2ecf20Sopenharmony_ci		parent = *p;
12548c2ecf20Sopenharmony_ci		e = rb_entry(parent, struct size_entry, rb);
12558c2ecf20Sopenharmony_ci		if (inum < e->inum)
12568c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
12578c2ecf20Sopenharmony_ci		else
12588c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
12598c2ecf20Sopenharmony_ci	}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	e = kzalloc(sizeof(struct size_entry), GFP_KERNEL);
12628c2ecf20Sopenharmony_ci	if (!e)
12638c2ecf20Sopenharmony_ci		return -ENOMEM;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	e->inum = inum;
12668c2ecf20Sopenharmony_ci	e->i_size = i_size;
12678c2ecf20Sopenharmony_ci	e->d_size = d_size;
12688c2ecf20Sopenharmony_ci	e->exists = exists;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	rb_link_node(&e->rb, parent, p);
12718c2ecf20Sopenharmony_ci	rb_insert_color(&e->rb, &c->size_tree);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	return 0;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci/**
12778c2ecf20Sopenharmony_ci * find_ino - find an entry on the size tree.
12788c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
12798c2ecf20Sopenharmony_ci * @inum: inode number
12808c2ecf20Sopenharmony_ci */
12818c2ecf20Sopenharmony_cistatic struct size_entry *find_ino(struct ubifs_info *c, ino_t inum)
12828c2ecf20Sopenharmony_ci{
12838c2ecf20Sopenharmony_ci	struct rb_node *p = c->size_tree.rb_node;
12848c2ecf20Sopenharmony_ci	struct size_entry *e;
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	while (p) {
12878c2ecf20Sopenharmony_ci		e = rb_entry(p, struct size_entry, rb);
12888c2ecf20Sopenharmony_ci		if (inum < e->inum)
12898c2ecf20Sopenharmony_ci			p = p->rb_left;
12908c2ecf20Sopenharmony_ci		else if (inum > e->inum)
12918c2ecf20Sopenharmony_ci			p = p->rb_right;
12928c2ecf20Sopenharmony_ci		else
12938c2ecf20Sopenharmony_ci			return e;
12948c2ecf20Sopenharmony_ci	}
12958c2ecf20Sopenharmony_ci	return NULL;
12968c2ecf20Sopenharmony_ci}
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci/**
12998c2ecf20Sopenharmony_ci * remove_ino - remove an entry from the size tree.
13008c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
13018c2ecf20Sopenharmony_ci * @inum: inode number
13028c2ecf20Sopenharmony_ci */
13038c2ecf20Sopenharmony_cistatic void remove_ino(struct ubifs_info *c, ino_t inum)
13048c2ecf20Sopenharmony_ci{
13058c2ecf20Sopenharmony_ci	struct size_entry *e = find_ino(c, inum);
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	if (!e)
13088c2ecf20Sopenharmony_ci		return;
13098c2ecf20Sopenharmony_ci	rb_erase(&e->rb, &c->size_tree);
13108c2ecf20Sopenharmony_ci	kfree(e);
13118c2ecf20Sopenharmony_ci}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci/**
13148c2ecf20Sopenharmony_ci * ubifs_destroy_size_tree - free resources related to the size tree.
13158c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
13168c2ecf20Sopenharmony_ci */
13178c2ecf20Sopenharmony_civoid ubifs_destroy_size_tree(struct ubifs_info *c)
13188c2ecf20Sopenharmony_ci{
13198c2ecf20Sopenharmony_ci	struct size_entry *e, *n;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) {
13228c2ecf20Sopenharmony_ci		iput(e->inode);
13238c2ecf20Sopenharmony_ci		kfree(e);
13248c2ecf20Sopenharmony_ci	}
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	c->size_tree = RB_ROOT;
13278c2ecf20Sopenharmony_ci}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci/**
13308c2ecf20Sopenharmony_ci * ubifs_recover_size_accum - accumulate inode sizes for recovery.
13318c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
13328c2ecf20Sopenharmony_ci * @key: node key
13338c2ecf20Sopenharmony_ci * @deletion: node is for a deletion
13348c2ecf20Sopenharmony_ci * @new_size: inode size
13358c2ecf20Sopenharmony_ci *
13368c2ecf20Sopenharmony_ci * This function has two purposes:
13378c2ecf20Sopenharmony_ci *     1) to ensure there are no data nodes that fall outside the inode size
13388c2ecf20Sopenharmony_ci *     2) to ensure there are no data nodes for inodes that do not exist
13398c2ecf20Sopenharmony_ci * To accomplish those purposes, a rb-tree is constructed containing an entry
13408c2ecf20Sopenharmony_ci * for each inode number in the journal that has not been deleted, and recording
13418c2ecf20Sopenharmony_ci * the size from the inode node, the maximum size of any data node (also altered
13428c2ecf20Sopenharmony_ci * by truncations) and a flag indicating a inode number for which no inode node
13438c2ecf20Sopenharmony_ci * was present in the journal.
13448c2ecf20Sopenharmony_ci *
13458c2ecf20Sopenharmony_ci * Note that there is still the possibility that there are data nodes that have
13468c2ecf20Sopenharmony_ci * been committed that are beyond the inode size, however the only way to find
13478c2ecf20Sopenharmony_ci * them would be to scan the entire index. Alternatively, some provision could
13488c2ecf20Sopenharmony_ci * be made to record the size of inodes at the start of commit, which would seem
13498c2ecf20Sopenharmony_ci * very cumbersome for a scenario that is quite unlikely and the only negative
13508c2ecf20Sopenharmony_ci * consequence of which is wasted space.
13518c2ecf20Sopenharmony_ci *
13528c2ecf20Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure.
13538c2ecf20Sopenharmony_ci */
13548c2ecf20Sopenharmony_ciint ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
13558c2ecf20Sopenharmony_ci			     int deletion, loff_t new_size)
13568c2ecf20Sopenharmony_ci{
13578c2ecf20Sopenharmony_ci	ino_t inum = key_inum(c, key);
13588c2ecf20Sopenharmony_ci	struct size_entry *e;
13598c2ecf20Sopenharmony_ci	int err;
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	switch (key_type(c, key)) {
13628c2ecf20Sopenharmony_ci	case UBIFS_INO_KEY:
13638c2ecf20Sopenharmony_ci		if (deletion)
13648c2ecf20Sopenharmony_ci			remove_ino(c, inum);
13658c2ecf20Sopenharmony_ci		else {
13668c2ecf20Sopenharmony_ci			e = find_ino(c, inum);
13678c2ecf20Sopenharmony_ci			if (e) {
13688c2ecf20Sopenharmony_ci				e->i_size = new_size;
13698c2ecf20Sopenharmony_ci				e->exists = 1;
13708c2ecf20Sopenharmony_ci			} else {
13718c2ecf20Sopenharmony_ci				err = add_ino(c, inum, new_size, 0, 1);
13728c2ecf20Sopenharmony_ci				if (err)
13738c2ecf20Sopenharmony_ci					return err;
13748c2ecf20Sopenharmony_ci			}
13758c2ecf20Sopenharmony_ci		}
13768c2ecf20Sopenharmony_ci		break;
13778c2ecf20Sopenharmony_ci	case UBIFS_DATA_KEY:
13788c2ecf20Sopenharmony_ci		e = find_ino(c, inum);
13798c2ecf20Sopenharmony_ci		if (e) {
13808c2ecf20Sopenharmony_ci			if (new_size > e->d_size)
13818c2ecf20Sopenharmony_ci				e->d_size = new_size;
13828c2ecf20Sopenharmony_ci		} else {
13838c2ecf20Sopenharmony_ci			err = add_ino(c, inum, 0, new_size, 0);
13848c2ecf20Sopenharmony_ci			if (err)
13858c2ecf20Sopenharmony_ci				return err;
13868c2ecf20Sopenharmony_ci		}
13878c2ecf20Sopenharmony_ci		break;
13888c2ecf20Sopenharmony_ci	case UBIFS_TRUN_KEY:
13898c2ecf20Sopenharmony_ci		e = find_ino(c, inum);
13908c2ecf20Sopenharmony_ci		if (e)
13918c2ecf20Sopenharmony_ci			e->d_size = new_size;
13928c2ecf20Sopenharmony_ci		break;
13938c2ecf20Sopenharmony_ci	}
13948c2ecf20Sopenharmony_ci	return 0;
13958c2ecf20Sopenharmony_ci}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci/**
13988c2ecf20Sopenharmony_ci * fix_size_in_place - fix inode size in place on flash.
13998c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
14008c2ecf20Sopenharmony_ci * @e: inode size information for recovery
14018c2ecf20Sopenharmony_ci */
14028c2ecf20Sopenharmony_cistatic int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
14038c2ecf20Sopenharmony_ci{
14048c2ecf20Sopenharmony_ci	struct ubifs_ino_node *ino = c->sbuf;
14058c2ecf20Sopenharmony_ci	unsigned char *p;
14068c2ecf20Sopenharmony_ci	union ubifs_key key;
14078c2ecf20Sopenharmony_ci	int err, lnum, offs, len;
14088c2ecf20Sopenharmony_ci	loff_t i_size;
14098c2ecf20Sopenharmony_ci	uint32_t crc;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	/* Locate the inode node LEB number and offset */
14128c2ecf20Sopenharmony_ci	ino_key_init(c, &key, e->inum);
14138c2ecf20Sopenharmony_ci	err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs);
14148c2ecf20Sopenharmony_ci	if (err)
14158c2ecf20Sopenharmony_ci		goto out;
14168c2ecf20Sopenharmony_ci	/*
14178c2ecf20Sopenharmony_ci	 * If the size recorded on the inode node is greater than the size that
14188c2ecf20Sopenharmony_ci	 * was calculated from nodes in the journal then don't change the inode.
14198c2ecf20Sopenharmony_ci	 */
14208c2ecf20Sopenharmony_ci	i_size = le64_to_cpu(ino->size);
14218c2ecf20Sopenharmony_ci	if (i_size >= e->d_size)
14228c2ecf20Sopenharmony_ci		return 0;
14238c2ecf20Sopenharmony_ci	/* Read the LEB */
14248c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
14258c2ecf20Sopenharmony_ci	if (err)
14268c2ecf20Sopenharmony_ci		goto out;
14278c2ecf20Sopenharmony_ci	/* Change the size field and recalculate the CRC */
14288c2ecf20Sopenharmony_ci	ino = c->sbuf + offs;
14298c2ecf20Sopenharmony_ci	ino->size = cpu_to_le64(e->d_size);
14308c2ecf20Sopenharmony_ci	len = le32_to_cpu(ino->ch.len);
14318c2ecf20Sopenharmony_ci	crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8);
14328c2ecf20Sopenharmony_ci	ino->ch.crc = cpu_to_le32(crc);
14338c2ecf20Sopenharmony_ci	/* Work out where data in the LEB ends and free space begins */
14348c2ecf20Sopenharmony_ci	p = c->sbuf;
14358c2ecf20Sopenharmony_ci	len = c->leb_size - 1;
14368c2ecf20Sopenharmony_ci	while (p[len] == 0xff)
14378c2ecf20Sopenharmony_ci		len -= 1;
14388c2ecf20Sopenharmony_ci	len = ALIGN(len + 1, c->min_io_size);
14398c2ecf20Sopenharmony_ci	/* Atomically write the fixed LEB back again */
14408c2ecf20Sopenharmony_ci	err = ubifs_leb_change(c, lnum, c->sbuf, len);
14418c2ecf20Sopenharmony_ci	if (err)
14428c2ecf20Sopenharmony_ci		goto out;
14438c2ecf20Sopenharmony_ci	dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
14448c2ecf20Sopenharmony_ci		  (unsigned long)e->inum, lnum, offs, i_size, e->d_size);
14458c2ecf20Sopenharmony_ci	return 0;
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_ciout:
14488c2ecf20Sopenharmony_ci	ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d",
14498c2ecf20Sopenharmony_ci		   (unsigned long)e->inum, e->i_size, e->d_size, err);
14508c2ecf20Sopenharmony_ci	return err;
14518c2ecf20Sopenharmony_ci}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci/**
14548c2ecf20Sopenharmony_ci * inode_fix_size - fix inode size
14558c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
14568c2ecf20Sopenharmony_ci * @e: inode size information for recovery
14578c2ecf20Sopenharmony_ci */
14588c2ecf20Sopenharmony_cistatic int inode_fix_size(struct ubifs_info *c, struct size_entry *e)
14598c2ecf20Sopenharmony_ci{
14608c2ecf20Sopenharmony_ci	struct inode *inode;
14618c2ecf20Sopenharmony_ci	struct ubifs_inode *ui;
14628c2ecf20Sopenharmony_ci	int err;
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	if (c->ro_mount)
14658c2ecf20Sopenharmony_ci		ubifs_assert(c, !e->inode);
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	if (e->inode) {
14688c2ecf20Sopenharmony_ci		/* Remounting rw, pick up inode we stored earlier */
14698c2ecf20Sopenharmony_ci		inode = e->inode;
14708c2ecf20Sopenharmony_ci	} else {
14718c2ecf20Sopenharmony_ci		inode = ubifs_iget(c->vfs_sb, e->inum);
14728c2ecf20Sopenharmony_ci		if (IS_ERR(inode))
14738c2ecf20Sopenharmony_ci			return PTR_ERR(inode);
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci		if (inode->i_size >= e->d_size) {
14768c2ecf20Sopenharmony_ci			/*
14778c2ecf20Sopenharmony_ci			 * The original inode in the index already has a size
14788c2ecf20Sopenharmony_ci			 * big enough, nothing to do
14798c2ecf20Sopenharmony_ci			 */
14808c2ecf20Sopenharmony_ci			iput(inode);
14818c2ecf20Sopenharmony_ci			return 0;
14828c2ecf20Sopenharmony_ci		}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci		dbg_rcvry("ino %lu size %lld -> %lld",
14858c2ecf20Sopenharmony_ci			  (unsigned long)e->inum,
14868c2ecf20Sopenharmony_ci			  inode->i_size, e->d_size);
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci		ui = ubifs_inode(inode);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci		inode->i_size = e->d_size;
14918c2ecf20Sopenharmony_ci		ui->ui_size = e->d_size;
14928c2ecf20Sopenharmony_ci		ui->synced_i_size = e->d_size;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci		e->inode = inode;
14958c2ecf20Sopenharmony_ci	}
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	/*
14988c2ecf20Sopenharmony_ci	 * In readonly mode just keep the inode pinned in memory until we go
14998c2ecf20Sopenharmony_ci	 * readwrite. In readwrite mode write the inode to the journal with the
15008c2ecf20Sopenharmony_ci	 * fixed size.
15018c2ecf20Sopenharmony_ci	 */
15028c2ecf20Sopenharmony_ci	if (c->ro_mount)
15038c2ecf20Sopenharmony_ci		return 0;
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	err = ubifs_jnl_write_inode(c, inode);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	iput(inode);
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	if (err)
15108c2ecf20Sopenharmony_ci		return err;
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	rb_erase(&e->rb, &c->size_tree);
15138c2ecf20Sopenharmony_ci	kfree(e);
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	return 0;
15168c2ecf20Sopenharmony_ci}
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci/**
15198c2ecf20Sopenharmony_ci * ubifs_recover_size - recover inode size.
15208c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
15218c2ecf20Sopenharmony_ci * @in_place: If true, do a in-place size fixup
15228c2ecf20Sopenharmony_ci *
15238c2ecf20Sopenharmony_ci * This function attempts to fix inode size discrepancies identified by the
15248c2ecf20Sopenharmony_ci * 'ubifs_recover_size_accum()' function.
15258c2ecf20Sopenharmony_ci *
15268c2ecf20Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure.
15278c2ecf20Sopenharmony_ci */
15288c2ecf20Sopenharmony_ciint ubifs_recover_size(struct ubifs_info *c, bool in_place)
15298c2ecf20Sopenharmony_ci{
15308c2ecf20Sopenharmony_ci	struct rb_node *this = rb_first(&c->size_tree);
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	while (this) {
15338c2ecf20Sopenharmony_ci		struct size_entry *e;
15348c2ecf20Sopenharmony_ci		int err;
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci		e = rb_entry(this, struct size_entry, rb);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci		this = rb_next(this);
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci		if (!e->exists) {
15418c2ecf20Sopenharmony_ci			union ubifs_key key;
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci			ino_key_init(c, &key, e->inum);
15448c2ecf20Sopenharmony_ci			err = ubifs_tnc_lookup(c, &key, c->sbuf);
15458c2ecf20Sopenharmony_ci			if (err && err != -ENOENT)
15468c2ecf20Sopenharmony_ci				return err;
15478c2ecf20Sopenharmony_ci			if (err == -ENOENT) {
15488c2ecf20Sopenharmony_ci				/* Remove data nodes that have no inode */
15498c2ecf20Sopenharmony_ci				dbg_rcvry("removing ino %lu",
15508c2ecf20Sopenharmony_ci					  (unsigned long)e->inum);
15518c2ecf20Sopenharmony_ci				err = ubifs_tnc_remove_ino(c, e->inum);
15528c2ecf20Sopenharmony_ci				if (err)
15538c2ecf20Sopenharmony_ci					return err;
15548c2ecf20Sopenharmony_ci			} else {
15558c2ecf20Sopenharmony_ci				struct ubifs_ino_node *ino = c->sbuf;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci				e->exists = 1;
15588c2ecf20Sopenharmony_ci				e->i_size = le64_to_cpu(ino->size);
15598c2ecf20Sopenharmony_ci			}
15608c2ecf20Sopenharmony_ci		}
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci		if (e->exists && e->i_size < e->d_size) {
15638c2ecf20Sopenharmony_ci			ubifs_assert(c, !(c->ro_mount && in_place));
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci			/*
15668c2ecf20Sopenharmony_ci			 * We found data that is outside the found inode size,
15678c2ecf20Sopenharmony_ci			 * fixup the inode size
15688c2ecf20Sopenharmony_ci			 */
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci			if (in_place) {
15718c2ecf20Sopenharmony_ci				err = fix_size_in_place(c, e);
15728c2ecf20Sopenharmony_ci				if (err)
15738c2ecf20Sopenharmony_ci					return err;
15748c2ecf20Sopenharmony_ci				iput(e->inode);
15758c2ecf20Sopenharmony_ci			} else {
15768c2ecf20Sopenharmony_ci				err = inode_fix_size(c, e);
15778c2ecf20Sopenharmony_ci				if (err)
15788c2ecf20Sopenharmony_ci					return err;
15798c2ecf20Sopenharmony_ci				continue;
15808c2ecf20Sopenharmony_ci			}
15818c2ecf20Sopenharmony_ci		}
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci		rb_erase(&e->rb, &c->size_tree);
15848c2ecf20Sopenharmony_ci		kfree(e);
15858c2ecf20Sopenharmony_ci	}
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	return 0;
15888c2ecf20Sopenharmony_ci}
1589