162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file is part of UBIFS.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors: Adrian Hunter
862306a36Sopenharmony_ci *          Artem Bityutskiy (Битюцкий Артём)
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * This file implements functions needed to recover from unclean un-mounts.
1362306a36Sopenharmony_ci * When UBIFS is mounted, it checks a flag on the master node to determine if
1462306a36Sopenharmony_ci * an un-mount was completed successfully. If not, the process of mounting
1562306a36Sopenharmony_ci * incorporates additional checking and fixing of on-flash data structures.
1662306a36Sopenharmony_ci * UBIFS always cleans away all remnants of an unclean un-mount, so that
1762306a36Sopenharmony_ci * errors do not accumulate. However UBIFS defers recovery if it is mounted
1862306a36Sopenharmony_ci * read-only, and the flash is not modified in that case.
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * The general UBIFS approach to the recovery is that it recovers from
2162306a36Sopenharmony_ci * corruptions which could be caused by power cuts, but it refuses to recover
2262306a36Sopenharmony_ci * from corruption caused by other reasons. And UBIFS tries to distinguish
2362306a36Sopenharmony_ci * between these 2 reasons of corruptions and silently recover in the former
2462306a36Sopenharmony_ci * case and loudly complain in the latter case.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * UBIFS writes only to erased LEBs, so it writes only to the flash space
2762306a36Sopenharmony_ci * containing only 0xFFs. UBIFS also always writes strictly from the beginning
2862306a36Sopenharmony_ci * of the LEB to the end. And UBIFS assumes that the underlying flash media
2962306a36Sopenharmony_ci * writes in @c->max_write_size bytes at a time.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min.
3262306a36Sopenharmony_ci * I/O unit corresponding to offset X to contain corrupted data, all the
3362306a36Sopenharmony_ci * following min. I/O units have to contain empty space (all 0xFFs). If this is
3462306a36Sopenharmony_ci * not true, the corruption cannot be the result of a power cut, and UBIFS
3562306a36Sopenharmony_ci * refuses to mount.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include <linux/crc32.h>
3962306a36Sopenharmony_ci#include <linux/slab.h>
4062306a36Sopenharmony_ci#include "ubifs.h"
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/**
4362306a36Sopenharmony_ci * is_empty - determine whether a buffer is empty (contains all 0xff).
4462306a36Sopenharmony_ci * @buf: buffer to clean
4562306a36Sopenharmony_ci * @len: length of buffer
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * This function returns %1 if the buffer is empty (contains all 0xff) otherwise
4862306a36Sopenharmony_ci * %0 is returned.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_cistatic int is_empty(void *buf, int len)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	uint8_t *p = buf;
5362306a36Sopenharmony_ci	int i;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	for (i = 0; i < len; i++)
5662306a36Sopenharmony_ci		if (*p++ != 0xff)
5762306a36Sopenharmony_ci			return 0;
5862306a36Sopenharmony_ci	return 1;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/**
6262306a36Sopenharmony_ci * first_non_ff - find offset of the first non-0xff byte.
6362306a36Sopenharmony_ci * @buf: buffer to search in
6462306a36Sopenharmony_ci * @len: length of buffer
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci * This function returns offset of the first non-0xff byte in @buf or %-1 if
6762306a36Sopenharmony_ci * the buffer contains only 0xff bytes.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_cistatic int first_non_ff(void *buf, int len)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	uint8_t *p = buf;
7262306a36Sopenharmony_ci	int i;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	for (i = 0; i < len; i++)
7562306a36Sopenharmony_ci		if (*p++ != 0xff)
7662306a36Sopenharmony_ci			return i;
7762306a36Sopenharmony_ci	return -1;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/**
8162306a36Sopenharmony_ci * get_master_node - get the last valid master node allowing for corruption.
8262306a36Sopenharmony_ci * @c: UBIFS file-system description object
8362306a36Sopenharmony_ci * @lnum: LEB number
8462306a36Sopenharmony_ci * @pbuf: buffer containing the LEB read, is returned here
8562306a36Sopenharmony_ci * @mst: master node, if found, is returned here
8662306a36Sopenharmony_ci * @cor: corruption, if found, is returned here
8762306a36Sopenharmony_ci *
8862306a36Sopenharmony_ci * This function allocates a buffer, reads the LEB into it, and finds and
8962306a36Sopenharmony_ci * returns the last valid master node allowing for one area of corruption.
9062306a36Sopenharmony_ci * The corrupt area, if there is one, must be consistent with the assumption
9162306a36Sopenharmony_ci * that it is the result of an unclean unmount while the master node was being
9262306a36Sopenharmony_ci * written. Under those circumstances, it is valid to use the previously written
9362306a36Sopenharmony_ci * master node.
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_cistatic int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
9862306a36Sopenharmony_ci			   struct ubifs_mst_node **mst, void **cor)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	const int sz = c->mst_node_alsz;
10162306a36Sopenharmony_ci	int err, offs, len;
10262306a36Sopenharmony_ci	void *sbuf, *buf;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	sbuf = vmalloc(c->leb_size);
10562306a36Sopenharmony_ci	if (!sbuf)
10662306a36Sopenharmony_ci		return -ENOMEM;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
10962306a36Sopenharmony_ci	if (err && err != -EBADMSG)
11062306a36Sopenharmony_ci		goto out_free;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	/* Find the first position that is definitely not a node */
11362306a36Sopenharmony_ci	offs = 0;
11462306a36Sopenharmony_ci	buf = sbuf;
11562306a36Sopenharmony_ci	len = c->leb_size;
11662306a36Sopenharmony_ci	while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) {
11762306a36Sopenharmony_ci		struct ubifs_ch *ch = buf;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci		if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC)
12062306a36Sopenharmony_ci			break;
12162306a36Sopenharmony_ci		offs += sz;
12262306a36Sopenharmony_ci		buf  += sz;
12362306a36Sopenharmony_ci		len  -= sz;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci	/* See if there was a valid master node before that */
12662306a36Sopenharmony_ci	if (offs) {
12762306a36Sopenharmony_ci		int ret;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		offs -= sz;
13062306a36Sopenharmony_ci		buf  -= sz;
13162306a36Sopenharmony_ci		len  += sz;
13262306a36Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
13362306a36Sopenharmony_ci		if (ret != SCANNED_A_NODE && offs) {
13462306a36Sopenharmony_ci			/* Could have been corruption so check one place back */
13562306a36Sopenharmony_ci			offs -= sz;
13662306a36Sopenharmony_ci			buf  -= sz;
13762306a36Sopenharmony_ci			len  += sz;
13862306a36Sopenharmony_ci			ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
13962306a36Sopenharmony_ci			if (ret != SCANNED_A_NODE)
14062306a36Sopenharmony_ci				/*
14162306a36Sopenharmony_ci				 * We accept only one area of corruption because
14262306a36Sopenharmony_ci				 * we are assuming that it was caused while
14362306a36Sopenharmony_ci				 * trying to write a master node.
14462306a36Sopenharmony_ci				 */
14562306a36Sopenharmony_ci				goto out_err;
14662306a36Sopenharmony_ci		}
14762306a36Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
14862306a36Sopenharmony_ci			struct ubifs_ch *ch = buf;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci			if (ch->node_type != UBIFS_MST_NODE)
15162306a36Sopenharmony_ci				goto out_err;
15262306a36Sopenharmony_ci			dbg_rcvry("found a master node at %d:%d", lnum, offs);
15362306a36Sopenharmony_ci			*mst = buf;
15462306a36Sopenharmony_ci			offs += sz;
15562306a36Sopenharmony_ci			buf  += sz;
15662306a36Sopenharmony_ci			len  -= sz;
15762306a36Sopenharmony_ci		}
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci	/* Check for corruption */
16062306a36Sopenharmony_ci	if (offs < c->leb_size) {
16162306a36Sopenharmony_ci		if (!is_empty(buf, min_t(int, len, sz))) {
16262306a36Sopenharmony_ci			*cor = buf;
16362306a36Sopenharmony_ci			dbg_rcvry("found corruption at %d:%d", lnum, offs);
16462306a36Sopenharmony_ci		}
16562306a36Sopenharmony_ci		offs += sz;
16662306a36Sopenharmony_ci		buf  += sz;
16762306a36Sopenharmony_ci		len  -= sz;
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci	/* Check remaining empty space */
17062306a36Sopenharmony_ci	if (offs < c->leb_size)
17162306a36Sopenharmony_ci		if (!is_empty(buf, len))
17262306a36Sopenharmony_ci			goto out_err;
17362306a36Sopenharmony_ci	*pbuf = sbuf;
17462306a36Sopenharmony_ci	return 0;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ciout_err:
17762306a36Sopenharmony_ci	err = -EINVAL;
17862306a36Sopenharmony_ciout_free:
17962306a36Sopenharmony_ci	vfree(sbuf);
18062306a36Sopenharmony_ci	*mst = NULL;
18162306a36Sopenharmony_ci	*cor = NULL;
18262306a36Sopenharmony_ci	return err;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/**
18662306a36Sopenharmony_ci * write_rcvrd_mst_node - write recovered master node.
18762306a36Sopenharmony_ci * @c: UBIFS file-system description object
18862306a36Sopenharmony_ci * @mst: master node
18962306a36Sopenharmony_ci *
19062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
19162306a36Sopenharmony_ci */
19262306a36Sopenharmony_cistatic int write_rcvrd_mst_node(struct ubifs_info *c,
19362306a36Sopenharmony_ci				struct ubifs_mst_node *mst)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz;
19662306a36Sopenharmony_ci	__le32 save_flags;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	dbg_rcvry("recovery");
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	save_flags = mst->flags;
20162306a36Sopenharmony_ci	mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ,
20462306a36Sopenharmony_ci				      offsetof(struct ubifs_mst_node, hmac), 1);
20562306a36Sopenharmony_ci	if (err)
20662306a36Sopenharmony_ci		goto out;
20762306a36Sopenharmony_ci	err = ubifs_leb_change(c, lnum, mst, sz);
20862306a36Sopenharmony_ci	if (err)
20962306a36Sopenharmony_ci		goto out;
21062306a36Sopenharmony_ci	err = ubifs_leb_change(c, lnum + 1, mst, sz);
21162306a36Sopenharmony_ci	if (err)
21262306a36Sopenharmony_ci		goto out;
21362306a36Sopenharmony_ciout:
21462306a36Sopenharmony_ci	mst->flags = save_flags;
21562306a36Sopenharmony_ci	return err;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/**
21962306a36Sopenharmony_ci * ubifs_recover_master_node - recover the master node.
22062306a36Sopenharmony_ci * @c: UBIFS file-system description object
22162306a36Sopenharmony_ci *
22262306a36Sopenharmony_ci * This function recovers the master node from corruption that may occur due to
22362306a36Sopenharmony_ci * an unclean unmount.
22462306a36Sopenharmony_ci *
22562306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
22662306a36Sopenharmony_ci */
22762306a36Sopenharmony_ciint ubifs_recover_master_node(struct ubifs_info *c)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL;
23062306a36Sopenharmony_ci	struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst;
23162306a36Sopenharmony_ci	const int sz = c->mst_node_alsz;
23262306a36Sopenharmony_ci	int err, offs1, offs2;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	dbg_rcvry("recovery");
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1);
23762306a36Sopenharmony_ci	if (err)
23862306a36Sopenharmony_ci		goto out_free;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2);
24162306a36Sopenharmony_ci	if (err)
24262306a36Sopenharmony_ci		goto out_free;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (mst1) {
24562306a36Sopenharmony_ci		offs1 = (void *)mst1 - buf1;
24662306a36Sopenharmony_ci		if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) &&
24762306a36Sopenharmony_ci		    (offs1 == 0 && !cor1)) {
24862306a36Sopenharmony_ci			/*
24962306a36Sopenharmony_ci			 * mst1 was written by recovery at offset 0 with no
25062306a36Sopenharmony_ci			 * corruption.
25162306a36Sopenharmony_ci			 */
25262306a36Sopenharmony_ci			dbg_rcvry("recovery recovery");
25362306a36Sopenharmony_ci			mst = mst1;
25462306a36Sopenharmony_ci		} else if (mst2) {
25562306a36Sopenharmony_ci			offs2 = (void *)mst2 - buf2;
25662306a36Sopenharmony_ci			if (offs1 == offs2) {
25762306a36Sopenharmony_ci				/* Same offset, so must be the same */
25862306a36Sopenharmony_ci				if (ubifs_compare_master_node(c, mst1, mst2))
25962306a36Sopenharmony_ci					goto out_err;
26062306a36Sopenharmony_ci				mst = mst1;
26162306a36Sopenharmony_ci			} else if (offs2 + sz == offs1) {
26262306a36Sopenharmony_ci				/* 1st LEB was written, 2nd was not */
26362306a36Sopenharmony_ci				if (cor1)
26462306a36Sopenharmony_ci					goto out_err;
26562306a36Sopenharmony_ci				mst = mst1;
26662306a36Sopenharmony_ci			} else if (offs1 == 0 &&
26762306a36Sopenharmony_ci				   c->leb_size - offs2 - sz < sz) {
26862306a36Sopenharmony_ci				/* 1st LEB was unmapped and written, 2nd not */
26962306a36Sopenharmony_ci				if (cor1)
27062306a36Sopenharmony_ci					goto out_err;
27162306a36Sopenharmony_ci				mst = mst1;
27262306a36Sopenharmony_ci			} else
27362306a36Sopenharmony_ci				goto out_err;
27462306a36Sopenharmony_ci		} else {
27562306a36Sopenharmony_ci			/*
27662306a36Sopenharmony_ci			 * 2nd LEB was unmapped and about to be written, so
27762306a36Sopenharmony_ci			 * there must be only one master node in the first LEB
27862306a36Sopenharmony_ci			 * and no corruption.
27962306a36Sopenharmony_ci			 */
28062306a36Sopenharmony_ci			if (offs1 != 0 || cor1)
28162306a36Sopenharmony_ci				goto out_err;
28262306a36Sopenharmony_ci			mst = mst1;
28362306a36Sopenharmony_ci		}
28462306a36Sopenharmony_ci	} else {
28562306a36Sopenharmony_ci		if (!mst2)
28662306a36Sopenharmony_ci			goto out_err;
28762306a36Sopenharmony_ci		/*
28862306a36Sopenharmony_ci		 * 1st LEB was unmapped and about to be written, so there must
28962306a36Sopenharmony_ci		 * be no room left in 2nd LEB.
29062306a36Sopenharmony_ci		 */
29162306a36Sopenharmony_ci		offs2 = (void *)mst2 - buf2;
29262306a36Sopenharmony_ci		if (offs2 + sz + sz <= c->leb_size)
29362306a36Sopenharmony_ci			goto out_err;
29462306a36Sopenharmony_ci		mst = mst2;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	ubifs_msg(c, "recovered master node from LEB %d",
29862306a36Sopenharmony_ci		  (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1));
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	if (c->ro_mount) {
30362306a36Sopenharmony_ci		/* Read-only mode. Keep a copy for switching to rw mode */
30462306a36Sopenharmony_ci		c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
30562306a36Sopenharmony_ci		if (!c->rcvrd_mst_node) {
30662306a36Sopenharmony_ci			err = -ENOMEM;
30762306a36Sopenharmony_ci			goto out_free;
30862306a36Sopenharmony_ci		}
30962306a36Sopenharmony_ci		memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci		/*
31262306a36Sopenharmony_ci		 * We had to recover the master node, which means there was an
31362306a36Sopenharmony_ci		 * unclean reboot. However, it is possible that the master node
31462306a36Sopenharmony_ci		 * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
31562306a36Sopenharmony_ci		 * E.g., consider the following chain of events:
31662306a36Sopenharmony_ci		 *
31762306a36Sopenharmony_ci		 * 1. UBIFS was cleanly unmounted, so the master node is clean
31862306a36Sopenharmony_ci		 * 2. UBIFS is being mounted R/W and starts changing the master
31962306a36Sopenharmony_ci		 *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
32062306a36Sopenharmony_ci		 *    so this LEB ends up with some amount of garbage at the
32162306a36Sopenharmony_ci		 *    end.
32262306a36Sopenharmony_ci		 * 3. UBIFS is being mounted R/O. We reach this place and
32362306a36Sopenharmony_ci		 *    recover the master node from the second LEB
32462306a36Sopenharmony_ci		 *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
32562306a36Sopenharmony_ci		 *    because we are being mounted R/O. We have to defer the
32662306a36Sopenharmony_ci		 *    operation.
32762306a36Sopenharmony_ci		 * 4. However, this master node (@c->mst_node) is marked as
32862306a36Sopenharmony_ci		 *    clean (since the step 1). And if we just return, the
32962306a36Sopenharmony_ci		 *    mount code will be confused and won't recover the master
33062306a36Sopenharmony_ci		 *    node when it is re-mounter R/W later.
33162306a36Sopenharmony_ci		 *
33262306a36Sopenharmony_ci		 *    Thus, to force the recovery by marking the master node as
33362306a36Sopenharmony_ci		 *    dirty.
33462306a36Sopenharmony_ci		 */
33562306a36Sopenharmony_ci		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
33662306a36Sopenharmony_ci	} else {
33762306a36Sopenharmony_ci		/* Write the recovered master node */
33862306a36Sopenharmony_ci		c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
33962306a36Sopenharmony_ci		err = write_rcvrd_mst_node(c, c->mst_node);
34062306a36Sopenharmony_ci		if (err)
34162306a36Sopenharmony_ci			goto out_free;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	vfree(buf2);
34562306a36Sopenharmony_ci	vfree(buf1);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	return 0;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ciout_err:
35062306a36Sopenharmony_ci	err = -EINVAL;
35162306a36Sopenharmony_ciout_free:
35262306a36Sopenharmony_ci	ubifs_err(c, "failed to recover master node");
35362306a36Sopenharmony_ci	if (mst1) {
35462306a36Sopenharmony_ci		ubifs_err(c, "dumping first master node");
35562306a36Sopenharmony_ci		ubifs_dump_node(c, mst1, c->leb_size - ((void *)mst1 - buf1));
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci	if (mst2) {
35862306a36Sopenharmony_ci		ubifs_err(c, "dumping second master node");
35962306a36Sopenharmony_ci		ubifs_dump_node(c, mst2, c->leb_size - ((void *)mst2 - buf2));
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci	vfree(buf2);
36262306a36Sopenharmony_ci	vfree(buf1);
36362306a36Sopenharmony_ci	return err;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci/**
36762306a36Sopenharmony_ci * ubifs_write_rcvrd_mst_node - write the recovered master node.
36862306a36Sopenharmony_ci * @c: UBIFS file-system description object
36962306a36Sopenharmony_ci *
37062306a36Sopenharmony_ci * This function writes the master node that was recovered during mounting in
37162306a36Sopenharmony_ci * read-only mode and must now be written because we are remounting rw.
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
37462306a36Sopenharmony_ci */
37562306a36Sopenharmony_ciint ubifs_write_rcvrd_mst_node(struct ubifs_info *c)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	int err;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (!c->rcvrd_mst_node)
38062306a36Sopenharmony_ci		return 0;
38162306a36Sopenharmony_ci	c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
38262306a36Sopenharmony_ci	c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
38362306a36Sopenharmony_ci	err = write_rcvrd_mst_node(c, c->rcvrd_mst_node);
38462306a36Sopenharmony_ci	if (err)
38562306a36Sopenharmony_ci		return err;
38662306a36Sopenharmony_ci	kfree(c->rcvrd_mst_node);
38762306a36Sopenharmony_ci	c->rcvrd_mst_node = NULL;
38862306a36Sopenharmony_ci	return 0;
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci/**
39262306a36Sopenharmony_ci * is_last_write - determine if an offset was in the last write to a LEB.
39362306a36Sopenharmony_ci * @c: UBIFS file-system description object
39462306a36Sopenharmony_ci * @buf: buffer to check
39562306a36Sopenharmony_ci * @offs: offset to check
39662306a36Sopenharmony_ci *
39762306a36Sopenharmony_ci * This function returns %1 if @offs was in the last write to the LEB whose data
39862306a36Sopenharmony_ci * is in @buf, otherwise %0 is returned. The determination is made by checking
39962306a36Sopenharmony_ci * for subsequent empty space starting from the next @c->max_write_size
40062306a36Sopenharmony_ci * boundary.
40162306a36Sopenharmony_ci */
40262306a36Sopenharmony_cistatic int is_last_write(const struct ubifs_info *c, void *buf, int offs)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	int empty_offs, check_len;
40562306a36Sopenharmony_ci	uint8_t *p;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	/*
40862306a36Sopenharmony_ci	 * Round up to the next @c->max_write_size boundary i.e. @offs is in
40962306a36Sopenharmony_ci	 * the last wbuf written. After that should be empty space.
41062306a36Sopenharmony_ci	 */
41162306a36Sopenharmony_ci	empty_offs = ALIGN(offs + 1, c->max_write_size);
41262306a36Sopenharmony_ci	check_len = c->leb_size - empty_offs;
41362306a36Sopenharmony_ci	p = buf + empty_offs - offs;
41462306a36Sopenharmony_ci	return is_empty(p, check_len);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/**
41862306a36Sopenharmony_ci * clean_buf - clean the data from an LEB sitting in a buffer.
41962306a36Sopenharmony_ci * @c: UBIFS file-system description object
42062306a36Sopenharmony_ci * @buf: buffer to clean
42162306a36Sopenharmony_ci * @lnum: LEB number to clean
42262306a36Sopenharmony_ci * @offs: offset from which to clean
42362306a36Sopenharmony_ci * @len: length of buffer
42462306a36Sopenharmony_ci *
42562306a36Sopenharmony_ci * This function pads up to the next min_io_size boundary (if there is one) and
42662306a36Sopenharmony_ci * sets empty space to all 0xff. @buf, @offs and @len are updated to the next
42762306a36Sopenharmony_ci * @c->min_io_size boundary.
42862306a36Sopenharmony_ci */
42962306a36Sopenharmony_cistatic void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
43062306a36Sopenharmony_ci		      int *offs, int *len)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	int empty_offs, pad_len;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	ubifs_assert(c, !(*offs & 7));
43762306a36Sopenharmony_ci	empty_offs = ALIGN(*offs, c->min_io_size);
43862306a36Sopenharmony_ci	pad_len = empty_offs - *offs;
43962306a36Sopenharmony_ci	ubifs_pad(c, *buf, pad_len);
44062306a36Sopenharmony_ci	*offs += pad_len;
44162306a36Sopenharmony_ci	*buf += pad_len;
44262306a36Sopenharmony_ci	*len -= pad_len;
44362306a36Sopenharmony_ci	memset(*buf, 0xff, c->leb_size - empty_offs);
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci/**
44762306a36Sopenharmony_ci * no_more_nodes - determine if there are no more nodes in a buffer.
44862306a36Sopenharmony_ci * @c: UBIFS file-system description object
44962306a36Sopenharmony_ci * @buf: buffer to check
45062306a36Sopenharmony_ci * @len: length of buffer
45162306a36Sopenharmony_ci * @lnum: LEB number of the LEB from which @buf was read
45262306a36Sopenharmony_ci * @offs: offset from which @buf was read
45362306a36Sopenharmony_ci *
45462306a36Sopenharmony_ci * This function ensures that the corrupted node at @offs is the last thing
45562306a36Sopenharmony_ci * written to a LEB. This function returns %1 if more data is not found and
45662306a36Sopenharmony_ci * %0 if more data is found.
45762306a36Sopenharmony_ci */
45862306a36Sopenharmony_cistatic int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
45962306a36Sopenharmony_ci			int lnum, int offs)
46062306a36Sopenharmony_ci{
46162306a36Sopenharmony_ci	struct ubifs_ch *ch = buf;
46262306a36Sopenharmony_ci	int skip, dlen = le32_to_cpu(ch->len);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/* Check for empty space after the corrupt node's common header */
46562306a36Sopenharmony_ci	skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs;
46662306a36Sopenharmony_ci	if (is_empty(buf + skip, len - skip))
46762306a36Sopenharmony_ci		return 1;
46862306a36Sopenharmony_ci	/*
46962306a36Sopenharmony_ci	 * The area after the common header size is not empty, so the common
47062306a36Sopenharmony_ci	 * header must be intact. Check it.
47162306a36Sopenharmony_ci	 */
47262306a36Sopenharmony_ci	if (ubifs_check_node(c, buf, len, lnum, offs, 1, 0) != -EUCLEAN) {
47362306a36Sopenharmony_ci		dbg_rcvry("unexpected bad common header at %d:%d", lnum, offs);
47462306a36Sopenharmony_ci		return 0;
47562306a36Sopenharmony_ci	}
47662306a36Sopenharmony_ci	/* Now we know the corrupt node's length we can skip over it */
47762306a36Sopenharmony_ci	skip = ALIGN(offs + dlen, c->max_write_size) - offs;
47862306a36Sopenharmony_ci	/* After which there should be empty space */
47962306a36Sopenharmony_ci	if (is_empty(buf + skip, len - skip))
48062306a36Sopenharmony_ci		return 1;
48162306a36Sopenharmony_ci	dbg_rcvry("unexpected data at %d:%d", lnum, offs + skip);
48262306a36Sopenharmony_ci	return 0;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci/**
48662306a36Sopenharmony_ci * fix_unclean_leb - fix an unclean LEB.
48762306a36Sopenharmony_ci * @c: UBIFS file-system description object
48862306a36Sopenharmony_ci * @sleb: scanned LEB information
48962306a36Sopenharmony_ci * @start: offset where scan started
49062306a36Sopenharmony_ci */
49162306a36Sopenharmony_cistatic int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
49262306a36Sopenharmony_ci			   int start)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci	int lnum = sleb->lnum, endpt = start;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	/* Get the end offset of the last node we are keeping */
49762306a36Sopenharmony_ci	if (!list_empty(&sleb->nodes)) {
49862306a36Sopenharmony_ci		struct ubifs_scan_node *snod;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci		snod = list_entry(sleb->nodes.prev,
50162306a36Sopenharmony_ci				  struct ubifs_scan_node, list);
50262306a36Sopenharmony_ci		endpt = snod->offs + snod->len;
50362306a36Sopenharmony_ci	}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	if (c->ro_mount && !c->remounting_rw) {
50662306a36Sopenharmony_ci		/* Add to recovery list */
50762306a36Sopenharmony_ci		struct ubifs_unclean_leb *ucleb;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci		dbg_rcvry("need to fix LEB %d start %d endpt %d",
51062306a36Sopenharmony_ci			  lnum, start, sleb->endpt);
51162306a36Sopenharmony_ci		ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS);
51262306a36Sopenharmony_ci		if (!ucleb)
51362306a36Sopenharmony_ci			return -ENOMEM;
51462306a36Sopenharmony_ci		ucleb->lnum = lnum;
51562306a36Sopenharmony_ci		ucleb->endpt = endpt;
51662306a36Sopenharmony_ci		list_add_tail(&ucleb->list, &c->unclean_leb_list);
51762306a36Sopenharmony_ci	} else {
51862306a36Sopenharmony_ci		/* Write the fixed LEB back to flash */
51962306a36Sopenharmony_ci		int err;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci		dbg_rcvry("fixing LEB %d start %d endpt %d",
52262306a36Sopenharmony_ci			  lnum, start, sleb->endpt);
52362306a36Sopenharmony_ci		if (endpt == 0) {
52462306a36Sopenharmony_ci			err = ubifs_leb_unmap(c, lnum);
52562306a36Sopenharmony_ci			if (err)
52662306a36Sopenharmony_ci				return err;
52762306a36Sopenharmony_ci		} else {
52862306a36Sopenharmony_ci			int len = ALIGN(endpt, c->min_io_size);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci			if (start) {
53162306a36Sopenharmony_ci				err = ubifs_leb_read(c, lnum, sleb->buf, 0,
53262306a36Sopenharmony_ci						     start, 1);
53362306a36Sopenharmony_ci				if (err)
53462306a36Sopenharmony_ci					return err;
53562306a36Sopenharmony_ci			}
53662306a36Sopenharmony_ci			/* Pad to min_io_size */
53762306a36Sopenharmony_ci			if (len > endpt) {
53862306a36Sopenharmony_ci				int pad_len = len - ALIGN(endpt, 8);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci				if (pad_len > 0) {
54162306a36Sopenharmony_ci					void *buf = sleb->buf + len - pad_len;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci					ubifs_pad(c, buf, pad_len);
54462306a36Sopenharmony_ci				}
54562306a36Sopenharmony_ci			}
54662306a36Sopenharmony_ci			err = ubifs_leb_change(c, lnum, sleb->buf, len);
54762306a36Sopenharmony_ci			if (err)
54862306a36Sopenharmony_ci				return err;
54962306a36Sopenharmony_ci		}
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci	return 0;
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci/**
55562306a36Sopenharmony_ci * drop_last_group - drop the last group of nodes.
55662306a36Sopenharmony_ci * @sleb: scanned LEB information
55762306a36Sopenharmony_ci * @offs: offset of dropped nodes is returned here
55862306a36Sopenharmony_ci *
55962306a36Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last
56062306a36Sopenharmony_ci * group of nodes of the scanned LEB.
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_cistatic void drop_last_group(struct ubifs_scan_leb *sleb, int *offs)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	while (!list_empty(&sleb->nodes)) {
56562306a36Sopenharmony_ci		struct ubifs_scan_node *snod;
56662306a36Sopenharmony_ci		struct ubifs_ch *ch;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
56962306a36Sopenharmony_ci				  list);
57062306a36Sopenharmony_ci		ch = snod->node;
57162306a36Sopenharmony_ci		if (ch->group_type != UBIFS_IN_NODE_GROUP)
57262306a36Sopenharmony_ci			break;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci		dbg_rcvry("dropping grouped node at %d:%d",
57562306a36Sopenharmony_ci			  sleb->lnum, snod->offs);
57662306a36Sopenharmony_ci		*offs = snod->offs;
57762306a36Sopenharmony_ci		list_del(&snod->list);
57862306a36Sopenharmony_ci		kfree(snod);
57962306a36Sopenharmony_ci		sleb->nodes_cnt -= 1;
58062306a36Sopenharmony_ci	}
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci/**
58462306a36Sopenharmony_ci * drop_last_node - drop the last node.
58562306a36Sopenharmony_ci * @sleb: scanned LEB information
58662306a36Sopenharmony_ci * @offs: offset of dropped nodes is returned here
58762306a36Sopenharmony_ci *
58862306a36Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last
58962306a36Sopenharmony_ci * node of the scanned LEB.
59062306a36Sopenharmony_ci */
59162306a36Sopenharmony_cistatic void drop_last_node(struct ubifs_scan_leb *sleb, int *offs)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	struct ubifs_scan_node *snod;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	if (!list_empty(&sleb->nodes)) {
59662306a36Sopenharmony_ci		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
59762306a36Sopenharmony_ci				  list);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci		dbg_rcvry("dropping last node at %d:%d",
60062306a36Sopenharmony_ci			  sleb->lnum, snod->offs);
60162306a36Sopenharmony_ci		*offs = snod->offs;
60262306a36Sopenharmony_ci		list_del(&snod->list);
60362306a36Sopenharmony_ci		kfree(snod);
60462306a36Sopenharmony_ci		sleb->nodes_cnt -= 1;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci/**
60962306a36Sopenharmony_ci * ubifs_recover_leb - scan and recover a LEB.
61062306a36Sopenharmony_ci * @c: UBIFS file-system description object
61162306a36Sopenharmony_ci * @lnum: LEB number
61262306a36Sopenharmony_ci * @offs: offset
61362306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
61462306a36Sopenharmony_ci * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not
61562306a36Sopenharmony_ci *         belong to any journal head)
61662306a36Sopenharmony_ci *
61762306a36Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have
61862306a36Sopenharmony_ci * been caused by the unclean unmount from which we are attempting to recover.
61962306a36Sopenharmony_ci * Returns the scanned information on success and a negative error code on
62062306a36Sopenharmony_ci * failure.
62162306a36Sopenharmony_ci */
62262306a36Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
62362306a36Sopenharmony_ci					 int offs, void *sbuf, int jhead)
62462306a36Sopenharmony_ci{
62562306a36Sopenharmony_ci	int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit;
62662306a36Sopenharmony_ci	int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped;
62762306a36Sopenharmony_ci	struct ubifs_scan_leb *sleb;
62862306a36Sopenharmony_ci	void *buf = sbuf + offs;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	sleb = ubifs_start_scan(c, lnum, offs, sbuf);
63362306a36Sopenharmony_ci	if (IS_ERR(sleb))
63462306a36Sopenharmony_ci		return sleb;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	ubifs_assert(c, len >= 8);
63762306a36Sopenharmony_ci	while (len >= 8) {
63862306a36Sopenharmony_ci		dbg_scan("look at LEB %d:%d (%d bytes left)",
63962306a36Sopenharmony_ci			 lnum, offs, len);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci		cond_resched();
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		/*
64462306a36Sopenharmony_ci		 * Scan quietly until there is an error from which we cannot
64562306a36Sopenharmony_ci		 * recover
64662306a36Sopenharmony_ci		 */
64762306a36Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
64862306a36Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
64962306a36Sopenharmony_ci			/* A valid node, and not a padding node */
65062306a36Sopenharmony_ci			struct ubifs_ch *ch = buf;
65162306a36Sopenharmony_ci			int node_len;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci			err = ubifs_add_snod(c, sleb, buf, offs);
65462306a36Sopenharmony_ci			if (err)
65562306a36Sopenharmony_ci				goto error;
65662306a36Sopenharmony_ci			node_len = ALIGN(le32_to_cpu(ch->len), 8);
65762306a36Sopenharmony_ci			offs += node_len;
65862306a36Sopenharmony_ci			buf += node_len;
65962306a36Sopenharmony_ci			len -= node_len;
66062306a36Sopenharmony_ci		} else if (ret > 0) {
66162306a36Sopenharmony_ci			/* Padding bytes or a valid padding node */
66262306a36Sopenharmony_ci			offs += ret;
66362306a36Sopenharmony_ci			buf += ret;
66462306a36Sopenharmony_ci			len -= ret;
66562306a36Sopenharmony_ci		} else if (ret == SCANNED_EMPTY_SPACE ||
66662306a36Sopenharmony_ci			   ret == SCANNED_GARBAGE     ||
66762306a36Sopenharmony_ci			   ret == SCANNED_A_BAD_PAD_NODE ||
66862306a36Sopenharmony_ci			   ret == SCANNED_A_CORRUPT_NODE) {
66962306a36Sopenharmony_ci			dbg_rcvry("found corruption (%d) at %d:%d",
67062306a36Sopenharmony_ci				  ret, lnum, offs);
67162306a36Sopenharmony_ci			break;
67262306a36Sopenharmony_ci		} else {
67362306a36Sopenharmony_ci			ubifs_err(c, "unexpected return value %d", ret);
67462306a36Sopenharmony_ci			err = -EINVAL;
67562306a36Sopenharmony_ci			goto error;
67662306a36Sopenharmony_ci		}
67762306a36Sopenharmony_ci	}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE) {
68062306a36Sopenharmony_ci		if (!is_last_write(c, buf, offs))
68162306a36Sopenharmony_ci			goto corrupted_rescan;
68262306a36Sopenharmony_ci	} else if (ret == SCANNED_A_CORRUPT_NODE) {
68362306a36Sopenharmony_ci		if (!no_more_nodes(c, buf, len, lnum, offs))
68462306a36Sopenharmony_ci			goto corrupted_rescan;
68562306a36Sopenharmony_ci	} else if (!is_empty(buf, len)) {
68662306a36Sopenharmony_ci		if (!is_last_write(c, buf, offs)) {
68762306a36Sopenharmony_ci			int corruption = first_non_ff(buf, len);
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci			/*
69062306a36Sopenharmony_ci			 * See header comment for this file for more
69162306a36Sopenharmony_ci			 * explanations about the reasons we have this check.
69262306a36Sopenharmony_ci			 */
69362306a36Sopenharmony_ci			ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d",
69462306a36Sopenharmony_ci				  lnum, offs, corruption);
69562306a36Sopenharmony_ci			/* Make sure we dump interesting non-0xFF data */
69662306a36Sopenharmony_ci			offs += corruption;
69762306a36Sopenharmony_ci			buf += corruption;
69862306a36Sopenharmony_ci			goto corrupted;
69962306a36Sopenharmony_ci		}
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	min_io_unit = round_down(offs, c->min_io_size);
70362306a36Sopenharmony_ci	if (grouped)
70462306a36Sopenharmony_ci		/*
70562306a36Sopenharmony_ci		 * If nodes are grouped, always drop the incomplete group at
70662306a36Sopenharmony_ci		 * the end.
70762306a36Sopenharmony_ci		 */
70862306a36Sopenharmony_ci		drop_last_group(sleb, &offs);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	if (jhead == GCHD) {
71162306a36Sopenharmony_ci		/*
71262306a36Sopenharmony_ci		 * If this LEB belongs to the GC head then while we are in the
71362306a36Sopenharmony_ci		 * middle of the same min. I/O unit keep dropping nodes. So
71462306a36Sopenharmony_ci		 * basically, what we want is to make sure that the last min.
71562306a36Sopenharmony_ci		 * I/O unit where we saw the corruption is dropped completely
71662306a36Sopenharmony_ci		 * with all the uncorrupted nodes which may possibly sit there.
71762306a36Sopenharmony_ci		 *
71862306a36Sopenharmony_ci		 * In other words, let's name the min. I/O unit where the
71962306a36Sopenharmony_ci		 * corruption starts B, and the previous min. I/O unit A. The
72062306a36Sopenharmony_ci		 * below code tries to deal with a situation when half of B
72162306a36Sopenharmony_ci		 * contains valid nodes or the end of a valid node, and the
72262306a36Sopenharmony_ci		 * second half of B contains corrupted data or garbage. This
72362306a36Sopenharmony_ci		 * means that UBIFS had been writing to B just before the power
72462306a36Sopenharmony_ci		 * cut happened. I do not know how realistic is this scenario
72562306a36Sopenharmony_ci		 * that half of the min. I/O unit had been written successfully
72662306a36Sopenharmony_ci		 * and the other half not, but this is possible in our 'failure
72762306a36Sopenharmony_ci		 * mode emulation' infrastructure at least.
72862306a36Sopenharmony_ci		 *
72962306a36Sopenharmony_ci		 * So what is the problem, why we need to drop those nodes? Why
73062306a36Sopenharmony_ci		 * can't we just clean-up the second half of B by putting a
73162306a36Sopenharmony_ci		 * padding node there? We can, and this works fine with one
73262306a36Sopenharmony_ci		 * exception which was reproduced with power cut emulation
73362306a36Sopenharmony_ci		 * testing and happens extremely rarely.
73462306a36Sopenharmony_ci		 *
73562306a36Sopenharmony_ci		 * Imagine the file-system is full, we run GC which starts
73662306a36Sopenharmony_ci		 * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is
73762306a36Sopenharmony_ci		 * the current GC head LEB). The @c->gc_lnum is -1, which means
73862306a36Sopenharmony_ci		 * that GC will retain LEB X and will try to continue. Imagine
73962306a36Sopenharmony_ci		 * that LEB X is currently the dirtiest LEB, and the amount of
74062306a36Sopenharmony_ci		 * used space in LEB Y is exactly the same as amount of free
74162306a36Sopenharmony_ci		 * space in LEB X.
74262306a36Sopenharmony_ci		 *
74362306a36Sopenharmony_ci		 * And a power cut happens when nodes are moved from LEB X to
74462306a36Sopenharmony_ci		 * LEB Y. We are here trying to recover LEB Y which is the GC
74562306a36Sopenharmony_ci		 * head LEB. We find the min. I/O unit B as described above.
74662306a36Sopenharmony_ci		 * Then we clean-up LEB Y by padding min. I/O unit. And later
74762306a36Sopenharmony_ci		 * 'ubifs_rcvry_gc_commit()' function fails, because it cannot
74862306a36Sopenharmony_ci		 * find a dirty LEB which could be GC'd into LEB Y! Even LEB X
74962306a36Sopenharmony_ci		 * does not match because the amount of valid nodes there does
75062306a36Sopenharmony_ci		 * not fit the free space in LEB Y any more! And this is
75162306a36Sopenharmony_ci		 * because of the padding node which we added to LEB Y. The
75262306a36Sopenharmony_ci		 * user-visible effect of this which I once observed and
75362306a36Sopenharmony_ci		 * analysed is that we cannot mount the file-system with
75462306a36Sopenharmony_ci		 * -ENOSPC error.
75562306a36Sopenharmony_ci		 *
75662306a36Sopenharmony_ci		 * So obviously, to make sure that situation does not happen we
75762306a36Sopenharmony_ci		 * should free min. I/O unit B in LEB Y completely and the last
75862306a36Sopenharmony_ci		 * used min. I/O unit in LEB Y should be A. This is basically
75962306a36Sopenharmony_ci		 * what the below code tries to do.
76062306a36Sopenharmony_ci		 */
76162306a36Sopenharmony_ci		while (offs > min_io_unit)
76262306a36Sopenharmony_ci			drop_last_node(sleb, &offs);
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	buf = sbuf + offs;
76662306a36Sopenharmony_ci	len = c->leb_size - offs;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	clean_buf(c, &buf, lnum, &offs, &len);
76962306a36Sopenharmony_ci	ubifs_end_scan(c, sleb, lnum, offs);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	err = fix_unclean_leb(c, sleb, start);
77262306a36Sopenharmony_ci	if (err)
77362306a36Sopenharmony_ci		goto error;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	return sleb;
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_cicorrupted_rescan:
77862306a36Sopenharmony_ci	/* Re-scan the corrupted data with verbose messages */
77962306a36Sopenharmony_ci	ubifs_err(c, "corruption %d", ret);
78062306a36Sopenharmony_ci	ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
78162306a36Sopenharmony_cicorrupted:
78262306a36Sopenharmony_ci	ubifs_scanned_corruption(c, lnum, offs, buf);
78362306a36Sopenharmony_ci	err = -EUCLEAN;
78462306a36Sopenharmony_cierror:
78562306a36Sopenharmony_ci	ubifs_err(c, "LEB %d scanning failed", lnum);
78662306a36Sopenharmony_ci	ubifs_scan_destroy(sleb);
78762306a36Sopenharmony_ci	return ERR_PTR(err);
78862306a36Sopenharmony_ci}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci/**
79162306a36Sopenharmony_ci * get_cs_sqnum - get commit start sequence number.
79262306a36Sopenharmony_ci * @c: UBIFS file-system description object
79362306a36Sopenharmony_ci * @lnum: LEB number of commit start node
79462306a36Sopenharmony_ci * @offs: offset of commit start node
79562306a36Sopenharmony_ci * @cs_sqnum: commit start sequence number is returned here
79662306a36Sopenharmony_ci *
79762306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
79862306a36Sopenharmony_ci */
79962306a36Sopenharmony_cistatic int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
80062306a36Sopenharmony_ci			unsigned long long *cs_sqnum)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	struct ubifs_cs_node *cs_node = NULL;
80362306a36Sopenharmony_ci	int err, ret;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	dbg_rcvry("at %d:%d", lnum, offs);
80662306a36Sopenharmony_ci	cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL);
80762306a36Sopenharmony_ci	if (!cs_node)
80862306a36Sopenharmony_ci		return -ENOMEM;
80962306a36Sopenharmony_ci	if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
81062306a36Sopenharmony_ci		goto out_err;
81162306a36Sopenharmony_ci	err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
81262306a36Sopenharmony_ci			     UBIFS_CS_NODE_SZ, 0);
81362306a36Sopenharmony_ci	if (err && err != -EBADMSG)
81462306a36Sopenharmony_ci		goto out_free;
81562306a36Sopenharmony_ci	ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
81662306a36Sopenharmony_ci	if (ret != SCANNED_A_NODE) {
81762306a36Sopenharmony_ci		ubifs_err(c, "Not a valid node");
81862306a36Sopenharmony_ci		goto out_err;
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci	if (cs_node->ch.node_type != UBIFS_CS_NODE) {
82162306a36Sopenharmony_ci		ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type);
82262306a36Sopenharmony_ci		goto out_err;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci	if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
82562306a36Sopenharmony_ci		ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu",
82662306a36Sopenharmony_ci			  (unsigned long long)le64_to_cpu(cs_node->cmt_no),
82762306a36Sopenharmony_ci			  c->cmt_no);
82862306a36Sopenharmony_ci		goto out_err;
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci	*cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
83162306a36Sopenharmony_ci	dbg_rcvry("commit start sqnum %llu", *cs_sqnum);
83262306a36Sopenharmony_ci	kfree(cs_node);
83362306a36Sopenharmony_ci	return 0;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ciout_err:
83662306a36Sopenharmony_ci	err = -EINVAL;
83762306a36Sopenharmony_ciout_free:
83862306a36Sopenharmony_ci	ubifs_err(c, "failed to get CS sqnum");
83962306a36Sopenharmony_ci	kfree(cs_node);
84062306a36Sopenharmony_ci	return err;
84162306a36Sopenharmony_ci}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci/**
84462306a36Sopenharmony_ci * ubifs_recover_log_leb - scan and recover a log LEB.
84562306a36Sopenharmony_ci * @c: UBIFS file-system description object
84662306a36Sopenharmony_ci * @lnum: LEB number
84762306a36Sopenharmony_ci * @offs: offset
84862306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
84962306a36Sopenharmony_ci *
85062306a36Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have
85162306a36Sopenharmony_ci * been caused by unclean reboots from which we are attempting to recover
85262306a36Sopenharmony_ci * (assume that only the last log LEB can be corrupted by an unclean reboot).
85362306a36Sopenharmony_ci *
85462306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
85562306a36Sopenharmony_ci */
85662306a36Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
85762306a36Sopenharmony_ci					     int offs, void *sbuf)
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	struct ubifs_scan_leb *sleb;
86062306a36Sopenharmony_ci	int next_lnum;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	dbg_rcvry("LEB %d", lnum);
86362306a36Sopenharmony_ci	next_lnum = lnum + 1;
86462306a36Sopenharmony_ci	if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs)
86562306a36Sopenharmony_ci		next_lnum = UBIFS_LOG_LNUM;
86662306a36Sopenharmony_ci	if (next_lnum != c->ltail_lnum) {
86762306a36Sopenharmony_ci		/*
86862306a36Sopenharmony_ci		 * We can only recover at the end of the log, so check that the
86962306a36Sopenharmony_ci		 * next log LEB is empty or out of date.
87062306a36Sopenharmony_ci		 */
87162306a36Sopenharmony_ci		sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0);
87262306a36Sopenharmony_ci		if (IS_ERR(sleb))
87362306a36Sopenharmony_ci			return sleb;
87462306a36Sopenharmony_ci		if (sleb->nodes_cnt) {
87562306a36Sopenharmony_ci			struct ubifs_scan_node *snod;
87662306a36Sopenharmony_ci			unsigned long long cs_sqnum = c->cs_sqnum;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci			snod = list_entry(sleb->nodes.next,
87962306a36Sopenharmony_ci					  struct ubifs_scan_node, list);
88062306a36Sopenharmony_ci			if (cs_sqnum == 0) {
88162306a36Sopenharmony_ci				int err;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci				err = get_cs_sqnum(c, lnum, offs, &cs_sqnum);
88462306a36Sopenharmony_ci				if (err) {
88562306a36Sopenharmony_ci					ubifs_scan_destroy(sleb);
88662306a36Sopenharmony_ci					return ERR_PTR(err);
88762306a36Sopenharmony_ci				}
88862306a36Sopenharmony_ci			}
88962306a36Sopenharmony_ci			if (snod->sqnum > cs_sqnum) {
89062306a36Sopenharmony_ci				ubifs_err(c, "unrecoverable log corruption in LEB %d",
89162306a36Sopenharmony_ci					  lnum);
89262306a36Sopenharmony_ci				ubifs_scan_destroy(sleb);
89362306a36Sopenharmony_ci				return ERR_PTR(-EUCLEAN);
89462306a36Sopenharmony_ci			}
89562306a36Sopenharmony_ci		}
89662306a36Sopenharmony_ci		ubifs_scan_destroy(sleb);
89762306a36Sopenharmony_ci	}
89862306a36Sopenharmony_ci	return ubifs_recover_leb(c, lnum, offs, sbuf, -1);
89962306a36Sopenharmony_ci}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci/**
90262306a36Sopenharmony_ci * recover_head - recover a head.
90362306a36Sopenharmony_ci * @c: UBIFS file-system description object
90462306a36Sopenharmony_ci * @lnum: LEB number of head to recover
90562306a36Sopenharmony_ci * @offs: offset of head to recover
90662306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
90762306a36Sopenharmony_ci *
90862306a36Sopenharmony_ci * This function ensures that there is no data on the flash at a head location.
90962306a36Sopenharmony_ci *
91062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
91162306a36Sopenharmony_ci */
91262306a36Sopenharmony_cistatic int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
91362306a36Sopenharmony_ci{
91462306a36Sopenharmony_ci	int len = c->max_write_size, err;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	if (offs + len > c->leb_size)
91762306a36Sopenharmony_ci		len = c->leb_size - offs;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	if (!len)
92062306a36Sopenharmony_ci		return 0;
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	/* Read at the head location and check it is empty flash */
92362306a36Sopenharmony_ci	err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
92462306a36Sopenharmony_ci	if (err || !is_empty(sbuf, len)) {
92562306a36Sopenharmony_ci		dbg_rcvry("cleaning head at %d:%d", lnum, offs);
92662306a36Sopenharmony_ci		if (offs == 0)
92762306a36Sopenharmony_ci			return ubifs_leb_unmap(c, lnum);
92862306a36Sopenharmony_ci		err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
92962306a36Sopenharmony_ci		if (err)
93062306a36Sopenharmony_ci			return err;
93162306a36Sopenharmony_ci		return ubifs_leb_change(c, lnum, sbuf, offs);
93262306a36Sopenharmony_ci	}
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return 0;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci/**
93862306a36Sopenharmony_ci * ubifs_recover_inl_heads - recover index and LPT heads.
93962306a36Sopenharmony_ci * @c: UBIFS file-system description object
94062306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
94162306a36Sopenharmony_ci *
94262306a36Sopenharmony_ci * This function ensures that there is no data on the flash at the index and
94362306a36Sopenharmony_ci * LPT head locations.
94462306a36Sopenharmony_ci *
94562306a36Sopenharmony_ci * This deals with the recovery of a half-completed journal commit. UBIFS is
94662306a36Sopenharmony_ci * careful never to overwrite the last version of the index or the LPT. Because
94762306a36Sopenharmony_ci * the index and LPT are wandering trees, data from a half-completed commit will
94862306a36Sopenharmony_ci * not be referenced anywhere in UBIFS. The data will be either in LEBs that are
94962306a36Sopenharmony_ci * assumed to be empty and will be unmapped anyway before use, or in the index
95062306a36Sopenharmony_ci * and LPT heads.
95162306a36Sopenharmony_ci *
95262306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
95362306a36Sopenharmony_ci */
95462306a36Sopenharmony_ciint ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
95562306a36Sopenharmony_ci{
95662306a36Sopenharmony_ci	int err;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	ubifs_assert(c, !c->ro_mount || c->remounting_rw);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
96162306a36Sopenharmony_ci	err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
96262306a36Sopenharmony_ci	if (err)
96362306a36Sopenharmony_ci		return err;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs);
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
96862306a36Sopenharmony_ci}
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci/**
97162306a36Sopenharmony_ci * clean_an_unclean_leb - read and write a LEB to remove corruption.
97262306a36Sopenharmony_ci * @c: UBIFS file-system description object
97362306a36Sopenharmony_ci * @ucleb: unclean LEB information
97462306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
97562306a36Sopenharmony_ci *
97662306a36Sopenharmony_ci * This function reads a LEB up to a point pre-determined by the mount recovery,
97762306a36Sopenharmony_ci * checks the nodes, and writes the result back to the flash, thereby cleaning
97862306a36Sopenharmony_ci * off any following corruption, or non-fatal ECC errors.
97962306a36Sopenharmony_ci *
98062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
98162306a36Sopenharmony_ci */
98262306a36Sopenharmony_cistatic int clean_an_unclean_leb(struct ubifs_info *c,
98362306a36Sopenharmony_ci				struct ubifs_unclean_leb *ucleb, void *sbuf)
98462306a36Sopenharmony_ci{
98562306a36Sopenharmony_ci	int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
98662306a36Sopenharmony_ci	void *buf = sbuf;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	dbg_rcvry("LEB %d len %d", lnum, len);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	if (len == 0) {
99162306a36Sopenharmony_ci		/* Nothing to read, just unmap it */
99262306a36Sopenharmony_ci		return ubifs_leb_unmap(c, lnum);
99362306a36Sopenharmony_ci	}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
99662306a36Sopenharmony_ci	if (err && err != -EBADMSG)
99762306a36Sopenharmony_ci		return err;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	while (len >= 8) {
100062306a36Sopenharmony_ci		int ret;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci		cond_resched();
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		/* Scan quietly until there is an error */
100562306a36Sopenharmony_ci		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci		if (ret == SCANNED_A_NODE) {
100862306a36Sopenharmony_ci			/* A valid node, and not a padding node */
100962306a36Sopenharmony_ci			struct ubifs_ch *ch = buf;
101062306a36Sopenharmony_ci			int node_len;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci			node_len = ALIGN(le32_to_cpu(ch->len), 8);
101362306a36Sopenharmony_ci			offs += node_len;
101462306a36Sopenharmony_ci			buf += node_len;
101562306a36Sopenharmony_ci			len -= node_len;
101662306a36Sopenharmony_ci			continue;
101762306a36Sopenharmony_ci		}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci		if (ret > 0) {
102062306a36Sopenharmony_ci			/* Padding bytes or a valid padding node */
102162306a36Sopenharmony_ci			offs += ret;
102262306a36Sopenharmony_ci			buf += ret;
102362306a36Sopenharmony_ci			len -= ret;
102462306a36Sopenharmony_ci			continue;
102562306a36Sopenharmony_ci		}
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci		if (ret == SCANNED_EMPTY_SPACE) {
102862306a36Sopenharmony_ci			ubifs_err(c, "unexpected empty space at %d:%d",
102962306a36Sopenharmony_ci				  lnum, offs);
103062306a36Sopenharmony_ci			return -EUCLEAN;
103162306a36Sopenharmony_ci		}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci		if (quiet) {
103462306a36Sopenharmony_ci			/* Redo the last scan but noisily */
103562306a36Sopenharmony_ci			quiet = 0;
103662306a36Sopenharmony_ci			continue;
103762306a36Sopenharmony_ci		}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci		ubifs_scanned_corruption(c, lnum, offs, buf);
104062306a36Sopenharmony_ci		return -EUCLEAN;
104162306a36Sopenharmony_ci	}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	/* Pad to min_io_size */
104462306a36Sopenharmony_ci	len = ALIGN(ucleb->endpt, c->min_io_size);
104562306a36Sopenharmony_ci	if (len > ucleb->endpt) {
104662306a36Sopenharmony_ci		int pad_len = len - ALIGN(ucleb->endpt, 8);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci		if (pad_len > 0) {
104962306a36Sopenharmony_ci			buf = c->sbuf + len - pad_len;
105062306a36Sopenharmony_ci			ubifs_pad(c, buf, pad_len);
105162306a36Sopenharmony_ci		}
105262306a36Sopenharmony_ci	}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	/* Write back the LEB atomically */
105562306a36Sopenharmony_ci	err = ubifs_leb_change(c, lnum, sbuf, len);
105662306a36Sopenharmony_ci	if (err)
105762306a36Sopenharmony_ci		return err;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	dbg_rcvry("cleaned LEB %d", lnum);
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	return 0;
106262306a36Sopenharmony_ci}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci/**
106562306a36Sopenharmony_ci * ubifs_clean_lebs - clean LEBs recovered during read-only mount.
106662306a36Sopenharmony_ci * @c: UBIFS file-system description object
106762306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use
106862306a36Sopenharmony_ci *
106962306a36Sopenharmony_ci * This function cleans a LEB identified during recovery that needs to be
107062306a36Sopenharmony_ci * written but was not because UBIFS was mounted read-only. This happens when
107162306a36Sopenharmony_ci * remounting to read-write mode.
107262306a36Sopenharmony_ci *
107362306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
107462306a36Sopenharmony_ci */
107562306a36Sopenharmony_ciint ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
107662306a36Sopenharmony_ci{
107762306a36Sopenharmony_ci	dbg_rcvry("recovery");
107862306a36Sopenharmony_ci	while (!list_empty(&c->unclean_leb_list)) {
107962306a36Sopenharmony_ci		struct ubifs_unclean_leb *ucleb;
108062306a36Sopenharmony_ci		int err;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci		ucleb = list_entry(c->unclean_leb_list.next,
108362306a36Sopenharmony_ci				   struct ubifs_unclean_leb, list);
108462306a36Sopenharmony_ci		err = clean_an_unclean_leb(c, ucleb, sbuf);
108562306a36Sopenharmony_ci		if (err)
108662306a36Sopenharmony_ci			return err;
108762306a36Sopenharmony_ci		list_del(&ucleb->list);
108862306a36Sopenharmony_ci		kfree(ucleb);
108962306a36Sopenharmony_ci	}
109062306a36Sopenharmony_ci	return 0;
109162306a36Sopenharmony_ci}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci/**
109462306a36Sopenharmony_ci * grab_empty_leb - grab an empty LEB to use as GC LEB and run commit.
109562306a36Sopenharmony_ci * @c: UBIFS file-system description object
109662306a36Sopenharmony_ci *
109762306a36Sopenharmony_ci * This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty
109862306a36Sopenharmony_ci * LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns
109962306a36Sopenharmony_ci * zero in case of success and a negative error code in case of failure.
110062306a36Sopenharmony_ci */
110162306a36Sopenharmony_cistatic int grab_empty_leb(struct ubifs_info *c)
110262306a36Sopenharmony_ci{
110362306a36Sopenharmony_ci	int lnum, err;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	/*
110662306a36Sopenharmony_ci	 * Note, it is very important to first search for an empty LEB and then
110762306a36Sopenharmony_ci	 * run the commit, not vice-versa. The reason is that there might be
110862306a36Sopenharmony_ci	 * only one empty LEB at the moment, the one which has been the
110962306a36Sopenharmony_ci	 * @c->gc_lnum just before the power cut happened. During the regular
111062306a36Sopenharmony_ci	 * UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no
111162306a36Sopenharmony_ci	 * one but GC can grab it. But at this moment this single empty LEB is
111262306a36Sopenharmony_ci	 * not marked as taken, so if we run commit - what happens? Right, the
111362306a36Sopenharmony_ci	 * commit will grab it and write the index there. Remember that the
111462306a36Sopenharmony_ci	 * index always expands as long as there is free space, and it only
111562306a36Sopenharmony_ci	 * starts consolidating when we run out of space.
111662306a36Sopenharmony_ci	 *
111762306a36Sopenharmony_ci	 * IOW, if we run commit now, we might not be able to find a free LEB
111862306a36Sopenharmony_ci	 * after this.
111962306a36Sopenharmony_ci	 */
112062306a36Sopenharmony_ci	lnum = ubifs_find_free_leb_for_idx(c);
112162306a36Sopenharmony_ci	if (lnum < 0) {
112262306a36Sopenharmony_ci		ubifs_err(c, "could not find an empty LEB");
112362306a36Sopenharmony_ci		ubifs_dump_lprops(c);
112462306a36Sopenharmony_ci		ubifs_dump_budg(c, &c->bi);
112562306a36Sopenharmony_ci		return lnum;
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	/* Reset the index flag */
112962306a36Sopenharmony_ci	err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
113062306a36Sopenharmony_ci				  LPROPS_INDEX, 0);
113162306a36Sopenharmony_ci	if (err)
113262306a36Sopenharmony_ci		return err;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	c->gc_lnum = lnum;
113562306a36Sopenharmony_ci	dbg_rcvry("found empty LEB %d, run commit", lnum);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	return ubifs_run_commit(c);
113862306a36Sopenharmony_ci}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci/**
114162306a36Sopenharmony_ci * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit.
114262306a36Sopenharmony_ci * @c: UBIFS file-system description object
114362306a36Sopenharmony_ci *
114462306a36Sopenharmony_ci * Out-of-place garbage collection requires always one empty LEB with which to
114562306a36Sopenharmony_ci * start garbage collection. The LEB number is recorded in c->gc_lnum and is
114662306a36Sopenharmony_ci * written to the master node on unmounting. In the case of an unclean unmount
114762306a36Sopenharmony_ci * the value of gc_lnum recorded in the master node is out of date and cannot
114862306a36Sopenharmony_ci * be used. Instead, recovery must allocate an empty LEB for this purpose.
114962306a36Sopenharmony_ci * However, there may not be enough empty space, in which case it must be
115062306a36Sopenharmony_ci * possible to GC the dirtiest LEB into the GC head LEB.
115162306a36Sopenharmony_ci *
115262306a36Sopenharmony_ci * This function also runs the commit which causes the TNC updates from
115362306a36Sopenharmony_ci * size-recovery and orphans to be written to the flash. That is important to
115462306a36Sopenharmony_ci * ensure correct replay order for subsequent mounts.
115562306a36Sopenharmony_ci *
115662306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
115762306a36Sopenharmony_ci */
115862306a36Sopenharmony_ciint ubifs_rcvry_gc_commit(struct ubifs_info *c)
115962306a36Sopenharmony_ci{
116062306a36Sopenharmony_ci	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
116162306a36Sopenharmony_ci	struct ubifs_lprops lp;
116262306a36Sopenharmony_ci	int err;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	dbg_rcvry("GC head LEB %d, offs %d", wbuf->lnum, wbuf->offs);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	c->gc_lnum = -1;
116762306a36Sopenharmony_ci	if (wbuf->lnum == -1 || wbuf->offs == c->leb_size)
116862306a36Sopenharmony_ci		return grab_empty_leb(c);
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2);
117162306a36Sopenharmony_ci	if (err) {
117262306a36Sopenharmony_ci		if (err != -ENOSPC)
117362306a36Sopenharmony_ci			return err;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci		dbg_rcvry("could not find a dirty LEB");
117662306a36Sopenharmony_ci		return grab_empty_leb(c);
117762306a36Sopenharmony_ci	}
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	ubifs_assert(c, !(lp.flags & LPROPS_INDEX));
118062306a36Sopenharmony_ci	ubifs_assert(c, lp.free + lp.dirty >= wbuf->offs);
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	/*
118362306a36Sopenharmony_ci	 * We run the commit before garbage collection otherwise subsequent
118462306a36Sopenharmony_ci	 * mounts will see the GC and orphan deletion in a different order.
118562306a36Sopenharmony_ci	 */
118662306a36Sopenharmony_ci	dbg_rcvry("committing");
118762306a36Sopenharmony_ci	err = ubifs_run_commit(c);
118862306a36Sopenharmony_ci	if (err)
118962306a36Sopenharmony_ci		return err;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	dbg_rcvry("GC'ing LEB %d", lp.lnum);
119262306a36Sopenharmony_ci	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
119362306a36Sopenharmony_ci	err = ubifs_garbage_collect_leb(c, &lp);
119462306a36Sopenharmony_ci	if (err >= 0) {
119562306a36Sopenharmony_ci		int err2 = ubifs_wbuf_sync_nolock(wbuf);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci		if (err2)
119862306a36Sopenharmony_ci			err = err2;
119962306a36Sopenharmony_ci	}
120062306a36Sopenharmony_ci	mutex_unlock(&wbuf->io_mutex);
120162306a36Sopenharmony_ci	if (err < 0) {
120262306a36Sopenharmony_ci		ubifs_err(c, "GC failed, error %d", err);
120362306a36Sopenharmony_ci		if (err == -EAGAIN)
120462306a36Sopenharmony_ci			err = -EINVAL;
120562306a36Sopenharmony_ci		return err;
120662306a36Sopenharmony_ci	}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	ubifs_assert(c, err == LEB_RETAINED);
120962306a36Sopenharmony_ci	if (err != LEB_RETAINED)
121062306a36Sopenharmony_ci		return -EINVAL;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	err = ubifs_leb_unmap(c, c->gc_lnum);
121362306a36Sopenharmony_ci	if (err)
121462306a36Sopenharmony_ci		return err;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	dbg_rcvry("allocated LEB %d for GC", lp.lnum);
121762306a36Sopenharmony_ci	return 0;
121862306a36Sopenharmony_ci}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci/**
122162306a36Sopenharmony_ci * struct size_entry - inode size information for recovery.
122262306a36Sopenharmony_ci * @rb: link in the RB-tree of sizes
122362306a36Sopenharmony_ci * @inum: inode number
122462306a36Sopenharmony_ci * @i_size: size on inode
122562306a36Sopenharmony_ci * @d_size: maximum size based on data nodes
122662306a36Sopenharmony_ci * @exists: indicates whether the inode exists
122762306a36Sopenharmony_ci * @inode: inode if pinned in memory awaiting rw mode to fix it
122862306a36Sopenharmony_ci */
122962306a36Sopenharmony_cistruct size_entry {
123062306a36Sopenharmony_ci	struct rb_node rb;
123162306a36Sopenharmony_ci	ino_t inum;
123262306a36Sopenharmony_ci	loff_t i_size;
123362306a36Sopenharmony_ci	loff_t d_size;
123462306a36Sopenharmony_ci	int exists;
123562306a36Sopenharmony_ci	struct inode *inode;
123662306a36Sopenharmony_ci};
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci/**
123962306a36Sopenharmony_ci * add_ino - add an entry to the size tree.
124062306a36Sopenharmony_ci * @c: UBIFS file-system description object
124162306a36Sopenharmony_ci * @inum: inode number
124262306a36Sopenharmony_ci * @i_size: size on inode
124362306a36Sopenharmony_ci * @d_size: maximum size based on data nodes
124462306a36Sopenharmony_ci * @exists: indicates whether the inode exists
124562306a36Sopenharmony_ci */
124662306a36Sopenharmony_cistatic int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size,
124762306a36Sopenharmony_ci		   loff_t d_size, int exists)
124862306a36Sopenharmony_ci{
124962306a36Sopenharmony_ci	struct rb_node **p = &c->size_tree.rb_node, *parent = NULL;
125062306a36Sopenharmony_ci	struct size_entry *e;
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	while (*p) {
125362306a36Sopenharmony_ci		parent = *p;
125462306a36Sopenharmony_ci		e = rb_entry(parent, struct size_entry, rb);
125562306a36Sopenharmony_ci		if (inum < e->inum)
125662306a36Sopenharmony_ci			p = &(*p)->rb_left;
125762306a36Sopenharmony_ci		else
125862306a36Sopenharmony_ci			p = &(*p)->rb_right;
125962306a36Sopenharmony_ci	}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	e = kzalloc(sizeof(struct size_entry), GFP_KERNEL);
126262306a36Sopenharmony_ci	if (!e)
126362306a36Sopenharmony_ci		return -ENOMEM;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	e->inum = inum;
126662306a36Sopenharmony_ci	e->i_size = i_size;
126762306a36Sopenharmony_ci	e->d_size = d_size;
126862306a36Sopenharmony_ci	e->exists = exists;
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	rb_link_node(&e->rb, parent, p);
127162306a36Sopenharmony_ci	rb_insert_color(&e->rb, &c->size_tree);
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	return 0;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci/**
127762306a36Sopenharmony_ci * find_ino - find an entry on the size tree.
127862306a36Sopenharmony_ci * @c: UBIFS file-system description object
127962306a36Sopenharmony_ci * @inum: inode number
128062306a36Sopenharmony_ci */
128162306a36Sopenharmony_cistatic struct size_entry *find_ino(struct ubifs_info *c, ino_t inum)
128262306a36Sopenharmony_ci{
128362306a36Sopenharmony_ci	struct rb_node *p = c->size_tree.rb_node;
128462306a36Sopenharmony_ci	struct size_entry *e;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	while (p) {
128762306a36Sopenharmony_ci		e = rb_entry(p, struct size_entry, rb);
128862306a36Sopenharmony_ci		if (inum < e->inum)
128962306a36Sopenharmony_ci			p = p->rb_left;
129062306a36Sopenharmony_ci		else if (inum > e->inum)
129162306a36Sopenharmony_ci			p = p->rb_right;
129262306a36Sopenharmony_ci		else
129362306a36Sopenharmony_ci			return e;
129462306a36Sopenharmony_ci	}
129562306a36Sopenharmony_ci	return NULL;
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci/**
129962306a36Sopenharmony_ci * remove_ino - remove an entry from the size tree.
130062306a36Sopenharmony_ci * @c: UBIFS file-system description object
130162306a36Sopenharmony_ci * @inum: inode number
130262306a36Sopenharmony_ci */
130362306a36Sopenharmony_cistatic void remove_ino(struct ubifs_info *c, ino_t inum)
130462306a36Sopenharmony_ci{
130562306a36Sopenharmony_ci	struct size_entry *e = find_ino(c, inum);
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	if (!e)
130862306a36Sopenharmony_ci		return;
130962306a36Sopenharmony_ci	rb_erase(&e->rb, &c->size_tree);
131062306a36Sopenharmony_ci	kfree(e);
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci/**
131462306a36Sopenharmony_ci * ubifs_destroy_size_tree - free resources related to the size tree.
131562306a36Sopenharmony_ci * @c: UBIFS file-system description object
131662306a36Sopenharmony_ci */
131762306a36Sopenharmony_civoid ubifs_destroy_size_tree(struct ubifs_info *c)
131862306a36Sopenharmony_ci{
131962306a36Sopenharmony_ci	struct size_entry *e, *n;
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) {
132262306a36Sopenharmony_ci		iput(e->inode);
132362306a36Sopenharmony_ci		kfree(e);
132462306a36Sopenharmony_ci	}
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	c->size_tree = RB_ROOT;
132762306a36Sopenharmony_ci}
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci/**
133062306a36Sopenharmony_ci * ubifs_recover_size_accum - accumulate inode sizes for recovery.
133162306a36Sopenharmony_ci * @c: UBIFS file-system description object
133262306a36Sopenharmony_ci * @key: node key
133362306a36Sopenharmony_ci * @deletion: node is for a deletion
133462306a36Sopenharmony_ci * @new_size: inode size
133562306a36Sopenharmony_ci *
133662306a36Sopenharmony_ci * This function has two purposes:
133762306a36Sopenharmony_ci *     1) to ensure there are no data nodes that fall outside the inode size
133862306a36Sopenharmony_ci *     2) to ensure there are no data nodes for inodes that do not exist
133962306a36Sopenharmony_ci * To accomplish those purposes, a rb-tree is constructed containing an entry
134062306a36Sopenharmony_ci * for each inode number in the journal that has not been deleted, and recording
134162306a36Sopenharmony_ci * the size from the inode node, the maximum size of any data node (also altered
134262306a36Sopenharmony_ci * by truncations) and a flag indicating a inode number for which no inode node
134362306a36Sopenharmony_ci * was present in the journal.
134462306a36Sopenharmony_ci *
134562306a36Sopenharmony_ci * Note that there is still the possibility that there are data nodes that have
134662306a36Sopenharmony_ci * been committed that are beyond the inode size, however the only way to find
134762306a36Sopenharmony_ci * them would be to scan the entire index. Alternatively, some provision could
134862306a36Sopenharmony_ci * be made to record the size of inodes at the start of commit, which would seem
134962306a36Sopenharmony_ci * very cumbersome for a scenario that is quite unlikely and the only negative
135062306a36Sopenharmony_ci * consequence of which is wasted space.
135162306a36Sopenharmony_ci *
135262306a36Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure.
135362306a36Sopenharmony_ci */
135462306a36Sopenharmony_ciint ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
135562306a36Sopenharmony_ci			     int deletion, loff_t new_size)
135662306a36Sopenharmony_ci{
135762306a36Sopenharmony_ci	ino_t inum = key_inum(c, key);
135862306a36Sopenharmony_ci	struct size_entry *e;
135962306a36Sopenharmony_ci	int err;
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	switch (key_type(c, key)) {
136262306a36Sopenharmony_ci	case UBIFS_INO_KEY:
136362306a36Sopenharmony_ci		if (deletion)
136462306a36Sopenharmony_ci			remove_ino(c, inum);
136562306a36Sopenharmony_ci		else {
136662306a36Sopenharmony_ci			e = find_ino(c, inum);
136762306a36Sopenharmony_ci			if (e) {
136862306a36Sopenharmony_ci				e->i_size = new_size;
136962306a36Sopenharmony_ci				e->exists = 1;
137062306a36Sopenharmony_ci			} else {
137162306a36Sopenharmony_ci				err = add_ino(c, inum, new_size, 0, 1);
137262306a36Sopenharmony_ci				if (err)
137362306a36Sopenharmony_ci					return err;
137462306a36Sopenharmony_ci			}
137562306a36Sopenharmony_ci		}
137662306a36Sopenharmony_ci		break;
137762306a36Sopenharmony_ci	case UBIFS_DATA_KEY:
137862306a36Sopenharmony_ci		e = find_ino(c, inum);
137962306a36Sopenharmony_ci		if (e) {
138062306a36Sopenharmony_ci			if (new_size > e->d_size)
138162306a36Sopenharmony_ci				e->d_size = new_size;
138262306a36Sopenharmony_ci		} else {
138362306a36Sopenharmony_ci			err = add_ino(c, inum, 0, new_size, 0);
138462306a36Sopenharmony_ci			if (err)
138562306a36Sopenharmony_ci				return err;
138662306a36Sopenharmony_ci		}
138762306a36Sopenharmony_ci		break;
138862306a36Sopenharmony_ci	case UBIFS_TRUN_KEY:
138962306a36Sopenharmony_ci		e = find_ino(c, inum);
139062306a36Sopenharmony_ci		if (e)
139162306a36Sopenharmony_ci			e->d_size = new_size;
139262306a36Sopenharmony_ci		break;
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci	return 0;
139562306a36Sopenharmony_ci}
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci/**
139862306a36Sopenharmony_ci * fix_size_in_place - fix inode size in place on flash.
139962306a36Sopenharmony_ci * @c: UBIFS file-system description object
140062306a36Sopenharmony_ci * @e: inode size information for recovery
140162306a36Sopenharmony_ci */
140262306a36Sopenharmony_cistatic int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	struct ubifs_ino_node *ino = c->sbuf;
140562306a36Sopenharmony_ci	unsigned char *p;
140662306a36Sopenharmony_ci	union ubifs_key key;
140762306a36Sopenharmony_ci	int err, lnum, offs, len;
140862306a36Sopenharmony_ci	loff_t i_size;
140962306a36Sopenharmony_ci	uint32_t crc;
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	/* Locate the inode node LEB number and offset */
141262306a36Sopenharmony_ci	ino_key_init(c, &key, e->inum);
141362306a36Sopenharmony_ci	err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs);
141462306a36Sopenharmony_ci	if (err)
141562306a36Sopenharmony_ci		goto out;
141662306a36Sopenharmony_ci	/*
141762306a36Sopenharmony_ci	 * If the size recorded on the inode node is greater than the size that
141862306a36Sopenharmony_ci	 * was calculated from nodes in the journal then don't change the inode.
141962306a36Sopenharmony_ci	 */
142062306a36Sopenharmony_ci	i_size = le64_to_cpu(ino->size);
142162306a36Sopenharmony_ci	if (i_size >= e->d_size)
142262306a36Sopenharmony_ci		return 0;
142362306a36Sopenharmony_ci	/* Read the LEB */
142462306a36Sopenharmony_ci	err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
142562306a36Sopenharmony_ci	if (err)
142662306a36Sopenharmony_ci		goto out;
142762306a36Sopenharmony_ci	/* Change the size field and recalculate the CRC */
142862306a36Sopenharmony_ci	ino = c->sbuf + offs;
142962306a36Sopenharmony_ci	ino->size = cpu_to_le64(e->d_size);
143062306a36Sopenharmony_ci	len = le32_to_cpu(ino->ch.len);
143162306a36Sopenharmony_ci	crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8);
143262306a36Sopenharmony_ci	ino->ch.crc = cpu_to_le32(crc);
143362306a36Sopenharmony_ci	/* Work out where data in the LEB ends and free space begins */
143462306a36Sopenharmony_ci	p = c->sbuf;
143562306a36Sopenharmony_ci	len = c->leb_size - 1;
143662306a36Sopenharmony_ci	while (p[len] == 0xff)
143762306a36Sopenharmony_ci		len -= 1;
143862306a36Sopenharmony_ci	len = ALIGN(len + 1, c->min_io_size);
143962306a36Sopenharmony_ci	/* Atomically write the fixed LEB back again */
144062306a36Sopenharmony_ci	err = ubifs_leb_change(c, lnum, c->sbuf, len);
144162306a36Sopenharmony_ci	if (err)
144262306a36Sopenharmony_ci		goto out;
144362306a36Sopenharmony_ci	dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
144462306a36Sopenharmony_ci		  (unsigned long)e->inum, lnum, offs, i_size, e->d_size);
144562306a36Sopenharmony_ci	return 0;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ciout:
144862306a36Sopenharmony_ci	ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d",
144962306a36Sopenharmony_ci		   (unsigned long)e->inum, e->i_size, e->d_size, err);
145062306a36Sopenharmony_ci	return err;
145162306a36Sopenharmony_ci}
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci/**
145462306a36Sopenharmony_ci * inode_fix_size - fix inode size
145562306a36Sopenharmony_ci * @c: UBIFS file-system description object
145662306a36Sopenharmony_ci * @e: inode size information for recovery
145762306a36Sopenharmony_ci */
145862306a36Sopenharmony_cistatic int inode_fix_size(struct ubifs_info *c, struct size_entry *e)
145962306a36Sopenharmony_ci{
146062306a36Sopenharmony_ci	struct inode *inode;
146162306a36Sopenharmony_ci	struct ubifs_inode *ui;
146262306a36Sopenharmony_ci	int err;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	if (c->ro_mount)
146562306a36Sopenharmony_ci		ubifs_assert(c, !e->inode);
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	if (e->inode) {
146862306a36Sopenharmony_ci		/* Remounting rw, pick up inode we stored earlier */
146962306a36Sopenharmony_ci		inode = e->inode;
147062306a36Sopenharmony_ci	} else {
147162306a36Sopenharmony_ci		inode = ubifs_iget(c->vfs_sb, e->inum);
147262306a36Sopenharmony_ci		if (IS_ERR(inode))
147362306a36Sopenharmony_ci			return PTR_ERR(inode);
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci		if (inode->i_size >= e->d_size) {
147662306a36Sopenharmony_ci			/*
147762306a36Sopenharmony_ci			 * The original inode in the index already has a size
147862306a36Sopenharmony_ci			 * big enough, nothing to do
147962306a36Sopenharmony_ci			 */
148062306a36Sopenharmony_ci			iput(inode);
148162306a36Sopenharmony_ci			return 0;
148262306a36Sopenharmony_ci		}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci		dbg_rcvry("ino %lu size %lld -> %lld",
148562306a36Sopenharmony_ci			  (unsigned long)e->inum,
148662306a36Sopenharmony_ci			  inode->i_size, e->d_size);
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci		ui = ubifs_inode(inode);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci		inode->i_size = e->d_size;
149162306a36Sopenharmony_ci		ui->ui_size = e->d_size;
149262306a36Sopenharmony_ci		ui->synced_i_size = e->d_size;
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci		e->inode = inode;
149562306a36Sopenharmony_ci	}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	/*
149862306a36Sopenharmony_ci	 * In readonly mode just keep the inode pinned in memory until we go
149962306a36Sopenharmony_ci	 * readwrite. In readwrite mode write the inode to the journal with the
150062306a36Sopenharmony_ci	 * fixed size.
150162306a36Sopenharmony_ci	 */
150262306a36Sopenharmony_ci	if (c->ro_mount)
150362306a36Sopenharmony_ci		return 0;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	err = ubifs_jnl_write_inode(c, inode);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	iput(inode);
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	if (err)
151062306a36Sopenharmony_ci		return err;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	rb_erase(&e->rb, &c->size_tree);
151362306a36Sopenharmony_ci	kfree(e);
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	return 0;
151662306a36Sopenharmony_ci}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci/**
151962306a36Sopenharmony_ci * ubifs_recover_size - recover inode size.
152062306a36Sopenharmony_ci * @c: UBIFS file-system description object
152162306a36Sopenharmony_ci * @in_place: If true, do a in-place size fixup
152262306a36Sopenharmony_ci *
152362306a36Sopenharmony_ci * This function attempts to fix inode size discrepancies identified by the
152462306a36Sopenharmony_ci * 'ubifs_recover_size_accum()' function.
152562306a36Sopenharmony_ci *
152662306a36Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure.
152762306a36Sopenharmony_ci */
152862306a36Sopenharmony_ciint ubifs_recover_size(struct ubifs_info *c, bool in_place)
152962306a36Sopenharmony_ci{
153062306a36Sopenharmony_ci	struct rb_node *this = rb_first(&c->size_tree);
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	while (this) {
153362306a36Sopenharmony_ci		struct size_entry *e;
153462306a36Sopenharmony_ci		int err;
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci		e = rb_entry(this, struct size_entry, rb);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci		this = rb_next(this);
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci		if (!e->exists) {
154162306a36Sopenharmony_ci			union ubifs_key key;
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci			ino_key_init(c, &key, e->inum);
154462306a36Sopenharmony_ci			err = ubifs_tnc_lookup(c, &key, c->sbuf);
154562306a36Sopenharmony_ci			if (err && err != -ENOENT)
154662306a36Sopenharmony_ci				return err;
154762306a36Sopenharmony_ci			if (err == -ENOENT) {
154862306a36Sopenharmony_ci				/* Remove data nodes that have no inode */
154962306a36Sopenharmony_ci				dbg_rcvry("removing ino %lu",
155062306a36Sopenharmony_ci					  (unsigned long)e->inum);
155162306a36Sopenharmony_ci				err = ubifs_tnc_remove_ino(c, e->inum);
155262306a36Sopenharmony_ci				if (err)
155362306a36Sopenharmony_ci					return err;
155462306a36Sopenharmony_ci			} else {
155562306a36Sopenharmony_ci				struct ubifs_ino_node *ino = c->sbuf;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci				e->exists = 1;
155862306a36Sopenharmony_ci				e->i_size = le64_to_cpu(ino->size);
155962306a36Sopenharmony_ci			}
156062306a36Sopenharmony_ci		}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci		if (e->exists && e->i_size < e->d_size) {
156362306a36Sopenharmony_ci			ubifs_assert(c, !(c->ro_mount && in_place));
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci			/*
156662306a36Sopenharmony_ci			 * We found data that is outside the found inode size,
156762306a36Sopenharmony_ci			 * fixup the inode size
156862306a36Sopenharmony_ci			 */
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci			if (in_place) {
157162306a36Sopenharmony_ci				err = fix_size_in_place(c, e);
157262306a36Sopenharmony_ci				if (err)
157362306a36Sopenharmony_ci					return err;
157462306a36Sopenharmony_ci				iput(e->inode);
157562306a36Sopenharmony_ci			} else {
157662306a36Sopenharmony_ci				err = inode_fix_size(c, e);
157762306a36Sopenharmony_ci				if (err)
157862306a36Sopenharmony_ci					return err;
157962306a36Sopenharmony_ci				continue;
158062306a36Sopenharmony_ci			}
158162306a36Sopenharmony_ci		}
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		rb_erase(&e->rb, &c->size_tree);
158462306a36Sopenharmony_ci		kfree(e);
158562306a36Sopenharmony_ci	}
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	return 0;
158862306a36Sopenharmony_ci}
1589